18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This application is Copyright 2012 Red Hat, Inc. 38c2ecf20Sopenharmony_ci * Doug Ledford <dledford@redhat.com> 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * mq_open_tests is free software: you can redistribute it and/or modify 68c2ecf20Sopenharmony_ci * it under the terms of the GNU General Public License as published by 78c2ecf20Sopenharmony_ci * the Free Software Foundation, version 3. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * mq_open_tests is distributed in the hope that it will be useful, 108c2ecf20Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 118c2ecf20Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 128c2ecf20Sopenharmony_ci * GNU General Public License for more details. 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci * For the full text of the license, see <http://www.gnu.org/licenses/>. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * mq_open_tests.c 178c2ecf20Sopenharmony_ci * Tests the various situations that should either succeed or fail to 188c2ecf20Sopenharmony_ci * open a posix message queue and then reports whether or not they 198c2ecf20Sopenharmony_ci * did as they were supposed to. 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci#include <stdio.h> 238c2ecf20Sopenharmony_ci#include <stdlib.h> 248c2ecf20Sopenharmony_ci#include <unistd.h> 258c2ecf20Sopenharmony_ci#include <fcntl.h> 268c2ecf20Sopenharmony_ci#include <string.h> 278c2ecf20Sopenharmony_ci#include <limits.h> 288c2ecf20Sopenharmony_ci#include <errno.h> 298c2ecf20Sopenharmony_ci#include <sys/types.h> 308c2ecf20Sopenharmony_ci#include <sys/time.h> 318c2ecf20Sopenharmony_ci#include <sys/resource.h> 328c2ecf20Sopenharmony_ci#include <sys/stat.h> 338c2ecf20Sopenharmony_ci#include <mqueue.h> 348c2ecf20Sopenharmony_ci#include <error.h> 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci#include "../kselftest.h" 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_cistatic char *usage = 398c2ecf20Sopenharmony_ci"Usage:\n" 408c2ecf20Sopenharmony_ci" %s path\n" 418c2ecf20Sopenharmony_ci"\n" 428c2ecf20Sopenharmony_ci" path Path name of the message queue to create\n" 438c2ecf20Sopenharmony_ci"\n" 448c2ecf20Sopenharmony_ci" Note: this program must be run as root in order to enable all tests\n" 458c2ecf20Sopenharmony_ci"\n"; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_cichar *DEF_MSGS = "/proc/sys/fs/mqueue/msg_default"; 488c2ecf20Sopenharmony_cichar *DEF_MSGSIZE = "/proc/sys/fs/mqueue/msgsize_default"; 498c2ecf20Sopenharmony_cichar *MAX_MSGS = "/proc/sys/fs/mqueue/msg_max"; 508c2ecf20Sopenharmony_cichar *MAX_MSGSIZE = "/proc/sys/fs/mqueue/msgsize_max"; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ciint default_settings; 538c2ecf20Sopenharmony_cistruct rlimit saved_limits, cur_limits; 548c2ecf20Sopenharmony_ciint saved_def_msgs, saved_def_msgsize, saved_max_msgs, saved_max_msgsize; 558c2ecf20Sopenharmony_ciint cur_def_msgs, cur_def_msgsize, cur_max_msgs, cur_max_msgsize; 568c2ecf20Sopenharmony_ciFILE *def_msgs, *def_msgsize, *max_msgs, *max_msgsize; 578c2ecf20Sopenharmony_cichar *queue_path; 588c2ecf20Sopenharmony_cichar *default_queue_path = "/test1"; 598c2ecf20Sopenharmony_cimqd_t queue = -1; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_cistatic inline void __set(FILE *stream, int value, char *err_msg); 628c2ecf20Sopenharmony_civoid shutdown(int exit_val, char *err_cause, int line_no); 638c2ecf20Sopenharmony_cistatic inline int get(FILE *stream); 648c2ecf20Sopenharmony_cistatic inline void set(FILE *stream, int value); 658c2ecf20Sopenharmony_cistatic inline void getr(int type, struct rlimit *rlim); 668c2ecf20Sopenharmony_cistatic inline void setr(int type, struct rlimit *rlim); 678c2ecf20Sopenharmony_civoid validate_current_settings(); 688c2ecf20Sopenharmony_cistatic inline void test_queue(struct mq_attr *attr, struct mq_attr *result); 698c2ecf20Sopenharmony_cistatic inline int test_queue_fail(struct mq_attr *attr, struct mq_attr *result); 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic inline void __set(FILE *stream, int value, char *err_msg) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci rewind(stream); 748c2ecf20Sopenharmony_ci if (fprintf(stream, "%d", value) < 0) 758c2ecf20Sopenharmony_ci perror(err_msg); 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_civoid shutdown(int exit_val, char *err_cause, int line_no) 808c2ecf20Sopenharmony_ci{ 818c2ecf20Sopenharmony_ci static int in_shutdown = 0; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci /* In case we get called recursively by a set() call below */ 848c2ecf20Sopenharmony_ci if (in_shutdown++) 858c2ecf20Sopenharmony_ci return; 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci if (seteuid(0) == -1) 888c2ecf20Sopenharmony_ci perror("seteuid() failed"); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (queue != -1) 918c2ecf20Sopenharmony_ci if (mq_close(queue)) 928c2ecf20Sopenharmony_ci perror("mq_close() during shutdown"); 938c2ecf20Sopenharmony_ci if (queue_path) 948c2ecf20Sopenharmony_ci /* 958c2ecf20Sopenharmony_ci * Be silent if this fails, if we cleaned up already it's 968c2ecf20Sopenharmony_ci * expected to fail 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_ci mq_unlink(queue_path); 998c2ecf20Sopenharmony_ci if (default_settings) { 1008c2ecf20Sopenharmony_ci if (saved_def_msgs) 1018c2ecf20Sopenharmony_ci __set(def_msgs, saved_def_msgs, 1028c2ecf20Sopenharmony_ci "failed to restore saved_def_msgs"); 1038c2ecf20Sopenharmony_ci if (saved_def_msgsize) 1048c2ecf20Sopenharmony_ci __set(def_msgsize, saved_def_msgsize, 1058c2ecf20Sopenharmony_ci "failed to restore saved_def_msgsize"); 1068c2ecf20Sopenharmony_ci } 1078c2ecf20Sopenharmony_ci if (saved_max_msgs) 1088c2ecf20Sopenharmony_ci __set(max_msgs, saved_max_msgs, 1098c2ecf20Sopenharmony_ci "failed to restore saved_max_msgs"); 1108c2ecf20Sopenharmony_ci if (saved_max_msgsize) 1118c2ecf20Sopenharmony_ci __set(max_msgsize, saved_max_msgsize, 1128c2ecf20Sopenharmony_ci "failed to restore saved_max_msgsize"); 1138c2ecf20Sopenharmony_ci if (exit_val) 1148c2ecf20Sopenharmony_ci error(exit_val, errno, "%s at %d", err_cause, line_no); 1158c2ecf20Sopenharmony_ci exit(0); 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic inline int get(FILE *stream) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci int value; 1218c2ecf20Sopenharmony_ci rewind(stream); 1228c2ecf20Sopenharmony_ci if (fscanf(stream, "%d", &value) != 1) 1238c2ecf20Sopenharmony_ci shutdown(4, "Error reading /proc entry", __LINE__ - 1); 1248c2ecf20Sopenharmony_ci return value; 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic inline void set(FILE *stream, int value) 1288c2ecf20Sopenharmony_ci{ 1298c2ecf20Sopenharmony_ci int new_value; 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ci rewind(stream); 1328c2ecf20Sopenharmony_ci if (fprintf(stream, "%d", value) < 0) 1338c2ecf20Sopenharmony_ci return shutdown(5, "Failed writing to /proc file", 1348c2ecf20Sopenharmony_ci __LINE__ - 1); 1358c2ecf20Sopenharmony_ci new_value = get(stream); 1368c2ecf20Sopenharmony_ci if (new_value != value) 1378c2ecf20Sopenharmony_ci return shutdown(5, "We didn't get what we wrote to /proc back", 1388c2ecf20Sopenharmony_ci __LINE__ - 1); 1398c2ecf20Sopenharmony_ci} 1408c2ecf20Sopenharmony_ci 1418c2ecf20Sopenharmony_cistatic inline void getr(int type, struct rlimit *rlim) 1428c2ecf20Sopenharmony_ci{ 1438c2ecf20Sopenharmony_ci if (getrlimit(type, rlim)) 1448c2ecf20Sopenharmony_ci shutdown(6, "getrlimit()", __LINE__ - 1); 1458c2ecf20Sopenharmony_ci} 1468c2ecf20Sopenharmony_ci 1478c2ecf20Sopenharmony_cistatic inline void setr(int type, struct rlimit *rlim) 1488c2ecf20Sopenharmony_ci{ 1498c2ecf20Sopenharmony_ci if (setrlimit(type, rlim)) 1508c2ecf20Sopenharmony_ci shutdown(7, "setrlimit()", __LINE__ - 1); 1518c2ecf20Sopenharmony_ci} 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_civoid validate_current_settings() 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci int rlim_needed; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci if (cur_limits.rlim_cur < 4096) { 1588c2ecf20Sopenharmony_ci printf("Current rlimit value for POSIX message queue bytes is " 1598c2ecf20Sopenharmony_ci "unreasonably low,\nincreasing.\n\n"); 1608c2ecf20Sopenharmony_ci cur_limits.rlim_cur = 8192; 1618c2ecf20Sopenharmony_ci cur_limits.rlim_max = 16384; 1628c2ecf20Sopenharmony_ci setr(RLIMIT_MSGQUEUE, &cur_limits); 1638c2ecf20Sopenharmony_ci } 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci if (default_settings) { 1668c2ecf20Sopenharmony_ci rlim_needed = (cur_def_msgs + 1) * (cur_def_msgsize + 1 + 1678c2ecf20Sopenharmony_ci 2 * sizeof(void *)); 1688c2ecf20Sopenharmony_ci if (rlim_needed > cur_limits.rlim_cur) { 1698c2ecf20Sopenharmony_ci printf("Temporarily lowering default queue parameters " 1708c2ecf20Sopenharmony_ci "to something that will work\n" 1718c2ecf20Sopenharmony_ci "with the current rlimit values.\n\n"); 1728c2ecf20Sopenharmony_ci set(def_msgs, 10); 1738c2ecf20Sopenharmony_ci cur_def_msgs = 10; 1748c2ecf20Sopenharmony_ci set(def_msgsize, 128); 1758c2ecf20Sopenharmony_ci cur_def_msgsize = 128; 1768c2ecf20Sopenharmony_ci } 1778c2ecf20Sopenharmony_ci } else { 1788c2ecf20Sopenharmony_ci rlim_needed = (cur_max_msgs + 1) * (cur_max_msgsize + 1 + 1798c2ecf20Sopenharmony_ci 2 * sizeof(void *)); 1808c2ecf20Sopenharmony_ci if (rlim_needed > cur_limits.rlim_cur) { 1818c2ecf20Sopenharmony_ci printf("Temporarily lowering maximum queue parameters " 1828c2ecf20Sopenharmony_ci "to something that will work\n" 1838c2ecf20Sopenharmony_ci "with the current rlimit values in case this is " 1848c2ecf20Sopenharmony_ci "a kernel that ties the default\n" 1858c2ecf20Sopenharmony_ci "queue parameters to the maximum queue " 1868c2ecf20Sopenharmony_ci "parameters.\n\n"); 1878c2ecf20Sopenharmony_ci set(max_msgs, 10); 1888c2ecf20Sopenharmony_ci cur_max_msgs = 10; 1898c2ecf20Sopenharmony_ci set(max_msgsize, 128); 1908c2ecf20Sopenharmony_ci cur_max_msgsize = 128; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci } 1938c2ecf20Sopenharmony_ci} 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci/* 1968c2ecf20Sopenharmony_ci * test_queue - Test opening a queue, shutdown if we fail. This should 1978c2ecf20Sopenharmony_ci * only be called in situations that should never fail. We clean up 1988c2ecf20Sopenharmony_ci * after ourselves and return the queue attributes in *result. 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_cistatic inline void test_queue(struct mq_attr *attr, struct mq_attr *result) 2018c2ecf20Sopenharmony_ci{ 2028c2ecf20Sopenharmony_ci int flags = O_RDWR | O_EXCL | O_CREAT; 2038c2ecf20Sopenharmony_ci int perms = DEFFILEMODE; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci if ((queue = mq_open(queue_path, flags, perms, attr)) == -1) 2068c2ecf20Sopenharmony_ci shutdown(1, "mq_open()", __LINE__); 2078c2ecf20Sopenharmony_ci if (mq_getattr(queue, result)) 2088c2ecf20Sopenharmony_ci shutdown(1, "mq_getattr()", __LINE__); 2098c2ecf20Sopenharmony_ci if (mq_close(queue)) 2108c2ecf20Sopenharmony_ci shutdown(1, "mq_close()", __LINE__); 2118c2ecf20Sopenharmony_ci queue = -1; 2128c2ecf20Sopenharmony_ci if (mq_unlink(queue_path)) 2138c2ecf20Sopenharmony_ci shutdown(1, "mq_unlink()", __LINE__); 2148c2ecf20Sopenharmony_ci} 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci/* 2178c2ecf20Sopenharmony_ci * Same as test_queue above, but failure is not fatal. 2188c2ecf20Sopenharmony_ci * Returns: 2198c2ecf20Sopenharmony_ci * 0 - Failed to create a queue 2208c2ecf20Sopenharmony_ci * 1 - Created a queue, attributes in *result 2218c2ecf20Sopenharmony_ci */ 2228c2ecf20Sopenharmony_cistatic inline int test_queue_fail(struct mq_attr *attr, struct mq_attr *result) 2238c2ecf20Sopenharmony_ci{ 2248c2ecf20Sopenharmony_ci int flags = O_RDWR | O_EXCL | O_CREAT; 2258c2ecf20Sopenharmony_ci int perms = DEFFILEMODE; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci if ((queue = mq_open(queue_path, flags, perms, attr)) == -1) 2288c2ecf20Sopenharmony_ci return 0; 2298c2ecf20Sopenharmony_ci if (mq_getattr(queue, result)) 2308c2ecf20Sopenharmony_ci shutdown(1, "mq_getattr()", __LINE__); 2318c2ecf20Sopenharmony_ci if (mq_close(queue)) 2328c2ecf20Sopenharmony_ci shutdown(1, "mq_close()", __LINE__); 2338c2ecf20Sopenharmony_ci queue = -1; 2348c2ecf20Sopenharmony_ci if (mq_unlink(queue_path)) 2358c2ecf20Sopenharmony_ci shutdown(1, "mq_unlink()", __LINE__); 2368c2ecf20Sopenharmony_ci return 1; 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ciint main(int argc, char *argv[]) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci struct mq_attr attr, result; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci if (argc != 2) { 2448c2ecf20Sopenharmony_ci printf("Using Default queue path - %s\n", default_queue_path); 2458c2ecf20Sopenharmony_ci queue_path = default_queue_path; 2468c2ecf20Sopenharmony_ci } else { 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci /* 2498c2ecf20Sopenharmony_ci * Although we can create a msg queue with a non-absolute path name, 2508c2ecf20Sopenharmony_ci * unlink will fail. So, if the name doesn't start with a /, add one 2518c2ecf20Sopenharmony_ci * when we save it. 2528c2ecf20Sopenharmony_ci */ 2538c2ecf20Sopenharmony_ci if (*argv[1] == '/') 2548c2ecf20Sopenharmony_ci queue_path = strdup(argv[1]); 2558c2ecf20Sopenharmony_ci else { 2568c2ecf20Sopenharmony_ci queue_path = malloc(strlen(argv[1]) + 2); 2578c2ecf20Sopenharmony_ci if (!queue_path) { 2588c2ecf20Sopenharmony_ci perror("malloc()"); 2598c2ecf20Sopenharmony_ci exit(1); 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci queue_path[0] = '/'; 2628c2ecf20Sopenharmony_ci queue_path[1] = 0; 2638c2ecf20Sopenharmony_ci strcat(queue_path, argv[1]); 2648c2ecf20Sopenharmony_ci } 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci if (getuid() != 0) 2688c2ecf20Sopenharmony_ci ksft_exit_skip("Not running as root, but almost all tests " 2698c2ecf20Sopenharmony_ci "require root in order to modify\nsystem settings. " 2708c2ecf20Sopenharmony_ci "Exiting.\n"); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci /* Find out what files there are for us to make tweaks in */ 2738c2ecf20Sopenharmony_ci def_msgs = fopen(DEF_MSGS, "r+"); 2748c2ecf20Sopenharmony_ci def_msgsize = fopen(DEF_MSGSIZE, "r+"); 2758c2ecf20Sopenharmony_ci max_msgs = fopen(MAX_MSGS, "r+"); 2768c2ecf20Sopenharmony_ci max_msgsize = fopen(MAX_MSGSIZE, "r+"); 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci if (!max_msgs) 2798c2ecf20Sopenharmony_ci shutdown(2, "Failed to open msg_max", __LINE__); 2808c2ecf20Sopenharmony_ci if (!max_msgsize) 2818c2ecf20Sopenharmony_ci shutdown(2, "Failed to open msgsize_max", __LINE__); 2828c2ecf20Sopenharmony_ci if (def_msgs || def_msgsize) 2838c2ecf20Sopenharmony_ci default_settings = 1; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci /* Load up the current system values for everything we can */ 2868c2ecf20Sopenharmony_ci getr(RLIMIT_MSGQUEUE, &saved_limits); 2878c2ecf20Sopenharmony_ci cur_limits = saved_limits; 2888c2ecf20Sopenharmony_ci if (default_settings) { 2898c2ecf20Sopenharmony_ci saved_def_msgs = cur_def_msgs = get(def_msgs); 2908c2ecf20Sopenharmony_ci saved_def_msgsize = cur_def_msgsize = get(def_msgsize); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci saved_max_msgs = cur_max_msgs = get(max_msgs); 2938c2ecf20Sopenharmony_ci saved_max_msgsize = cur_max_msgsize = get(max_msgsize); 2948c2ecf20Sopenharmony_ci 2958c2ecf20Sopenharmony_ci /* Tell the user our initial state */ 2968c2ecf20Sopenharmony_ci printf("\nInitial system state:\n"); 2978c2ecf20Sopenharmony_ci printf("\tUsing queue path:\t\t%s\n", queue_path); 2988c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(soft):\t\t%ld\n", 2998c2ecf20Sopenharmony_ci (long) saved_limits.rlim_cur); 3008c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(hard):\t\t%ld\n", 3018c2ecf20Sopenharmony_ci (long) saved_limits.rlim_max); 3028c2ecf20Sopenharmony_ci printf("\tMaximum Message Size:\t\t%d\n", saved_max_msgsize); 3038c2ecf20Sopenharmony_ci printf("\tMaximum Queue Size:\t\t%d\n", saved_max_msgs); 3048c2ecf20Sopenharmony_ci if (default_settings) { 3058c2ecf20Sopenharmony_ci printf("\tDefault Message Size:\t\t%d\n", saved_def_msgsize); 3068c2ecf20Sopenharmony_ci printf("\tDefault Queue Size:\t\t%d\n", saved_def_msgs); 3078c2ecf20Sopenharmony_ci } else { 3088c2ecf20Sopenharmony_ci printf("\tDefault Message Size:\t\tNot Supported\n"); 3098c2ecf20Sopenharmony_ci printf("\tDefault Queue Size:\t\tNot Supported\n"); 3108c2ecf20Sopenharmony_ci } 3118c2ecf20Sopenharmony_ci printf("\n"); 3128c2ecf20Sopenharmony_ci 3138c2ecf20Sopenharmony_ci validate_current_settings(); 3148c2ecf20Sopenharmony_ci 3158c2ecf20Sopenharmony_ci printf("Adjusted system state for testing:\n"); 3168c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(soft):\t\t%ld\n", (long) cur_limits.rlim_cur); 3178c2ecf20Sopenharmony_ci printf("\tRLIMIT_MSGQUEUE(hard):\t\t%ld\n", (long) cur_limits.rlim_max); 3188c2ecf20Sopenharmony_ci printf("\tMaximum Message Size:\t\t%d\n", cur_max_msgsize); 3198c2ecf20Sopenharmony_ci printf("\tMaximum Queue Size:\t\t%d\n", cur_max_msgs); 3208c2ecf20Sopenharmony_ci if (default_settings) { 3218c2ecf20Sopenharmony_ci printf("\tDefault Message Size:\t\t%d\n", cur_def_msgsize); 3228c2ecf20Sopenharmony_ci printf("\tDefault Queue Size:\t\t%d\n", cur_def_msgs); 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci 3258c2ecf20Sopenharmony_ci printf("\n\nTest series 1, behavior when no attr struct " 3268c2ecf20Sopenharmony_ci "passed to mq_open:\n"); 3278c2ecf20Sopenharmony_ci if (!default_settings) { 3288c2ecf20Sopenharmony_ci test_queue(NULL, &result); 3298c2ecf20Sopenharmony_ci printf("Given sane system settings, mq_open without an attr " 3308c2ecf20Sopenharmony_ci "struct succeeds:\tPASS\n"); 3318c2ecf20Sopenharmony_ci if (result.mq_maxmsg != cur_max_msgs || 3328c2ecf20Sopenharmony_ci result.mq_msgsize != cur_max_msgsize) { 3338c2ecf20Sopenharmony_ci printf("Kernel does not support setting the default " 3348c2ecf20Sopenharmony_ci "mq attributes,\nbut also doesn't tie the " 3358c2ecf20Sopenharmony_ci "defaults to the maximums:\t\t\tPASS\n"); 3368c2ecf20Sopenharmony_ci } else { 3378c2ecf20Sopenharmony_ci set(max_msgs, ++cur_max_msgs); 3388c2ecf20Sopenharmony_ci set(max_msgsize, ++cur_max_msgsize); 3398c2ecf20Sopenharmony_ci test_queue(NULL, &result); 3408c2ecf20Sopenharmony_ci if (result.mq_maxmsg == cur_max_msgs && 3418c2ecf20Sopenharmony_ci result.mq_msgsize == cur_max_msgsize) 3428c2ecf20Sopenharmony_ci printf("Kernel does not support setting the " 3438c2ecf20Sopenharmony_ci "default mq attributes and\n" 3448c2ecf20Sopenharmony_ci "also ties system wide defaults to " 3458c2ecf20Sopenharmony_ci "the system wide maximums:\t\t" 3468c2ecf20Sopenharmony_ci "FAIL\n"); 3478c2ecf20Sopenharmony_ci else 3488c2ecf20Sopenharmony_ci printf("Kernel does not support setting the " 3498c2ecf20Sopenharmony_ci "default mq attributes,\n" 3508c2ecf20Sopenharmony_ci "but also doesn't tie the defaults to " 3518c2ecf20Sopenharmony_ci "the maximums:\t\t\tPASS\n"); 3528c2ecf20Sopenharmony_ci } 3538c2ecf20Sopenharmony_ci } else { 3548c2ecf20Sopenharmony_ci printf("Kernel supports setting defaults separately from " 3558c2ecf20Sopenharmony_ci "maximums:\t\tPASS\n"); 3568c2ecf20Sopenharmony_ci /* 3578c2ecf20Sopenharmony_ci * While we are here, go ahead and test that the kernel 3588c2ecf20Sopenharmony_ci * properly follows the default settings 3598c2ecf20Sopenharmony_ci */ 3608c2ecf20Sopenharmony_ci test_queue(NULL, &result); 3618c2ecf20Sopenharmony_ci printf("Given sane values, mq_open without an attr struct " 3628c2ecf20Sopenharmony_ci "succeeds:\t\tPASS\n"); 3638c2ecf20Sopenharmony_ci if (result.mq_maxmsg != cur_def_msgs || 3648c2ecf20Sopenharmony_ci result.mq_msgsize != cur_def_msgsize) 3658c2ecf20Sopenharmony_ci printf("Kernel supports setting defaults, but does " 3668c2ecf20Sopenharmony_ci "not actually honor them:\tFAIL\n\n"); 3678c2ecf20Sopenharmony_ci else { 3688c2ecf20Sopenharmony_ci set(def_msgs, ++cur_def_msgs); 3698c2ecf20Sopenharmony_ci set(def_msgsize, ++cur_def_msgsize); 3708c2ecf20Sopenharmony_ci /* In case max was the same as the default */ 3718c2ecf20Sopenharmony_ci set(max_msgs, ++cur_max_msgs); 3728c2ecf20Sopenharmony_ci set(max_msgsize, ++cur_max_msgsize); 3738c2ecf20Sopenharmony_ci test_queue(NULL, &result); 3748c2ecf20Sopenharmony_ci if (result.mq_maxmsg != cur_def_msgs || 3758c2ecf20Sopenharmony_ci result.mq_msgsize != cur_def_msgsize) 3768c2ecf20Sopenharmony_ci printf("Kernel supports setting defaults, but " 3778c2ecf20Sopenharmony_ci "does not actually honor them:\t" 3788c2ecf20Sopenharmony_ci "FAIL\n"); 3798c2ecf20Sopenharmony_ci else 3808c2ecf20Sopenharmony_ci printf("Kernel properly honors default setting " 3818c2ecf20Sopenharmony_ci "knobs:\t\t\t\tPASS\n"); 3828c2ecf20Sopenharmony_ci } 3838c2ecf20Sopenharmony_ci set(def_msgs, cur_max_msgs + 1); 3848c2ecf20Sopenharmony_ci cur_def_msgs = cur_max_msgs + 1; 3858c2ecf20Sopenharmony_ci set(def_msgsize, cur_max_msgsize + 1); 3868c2ecf20Sopenharmony_ci cur_def_msgsize = cur_max_msgsize + 1; 3878c2ecf20Sopenharmony_ci if (cur_def_msgs * (cur_def_msgsize + 2 * sizeof(void *)) >= 3888c2ecf20Sopenharmony_ci cur_limits.rlim_cur) { 3898c2ecf20Sopenharmony_ci cur_limits.rlim_cur = (cur_def_msgs + 2) * 3908c2ecf20Sopenharmony_ci (cur_def_msgsize + 2 * sizeof(void *)); 3918c2ecf20Sopenharmony_ci cur_limits.rlim_max = 2 * cur_limits.rlim_cur; 3928c2ecf20Sopenharmony_ci setr(RLIMIT_MSGQUEUE, &cur_limits); 3938c2ecf20Sopenharmony_ci } 3948c2ecf20Sopenharmony_ci if (test_queue_fail(NULL, &result)) { 3958c2ecf20Sopenharmony_ci if (result.mq_maxmsg == cur_max_msgs && 3968c2ecf20Sopenharmony_ci result.mq_msgsize == cur_max_msgsize) 3978c2ecf20Sopenharmony_ci printf("Kernel properly limits default values " 3988c2ecf20Sopenharmony_ci "to lesser of default/max:\t\tPASS\n"); 3998c2ecf20Sopenharmony_ci else 4008c2ecf20Sopenharmony_ci printf("Kernel does not properly set default " 4018c2ecf20Sopenharmony_ci "queue parameters when\ndefaults > " 4028c2ecf20Sopenharmony_ci "max:\t\t\t\t\t\t\t\tFAIL\n"); 4038c2ecf20Sopenharmony_ci } else 4048c2ecf20Sopenharmony_ci printf("Kernel fails to open mq because defaults are " 4058c2ecf20Sopenharmony_ci "greater than maximums:\tFAIL\n"); 4068c2ecf20Sopenharmony_ci set(def_msgs, --cur_def_msgs); 4078c2ecf20Sopenharmony_ci set(def_msgsize, --cur_def_msgsize); 4088c2ecf20Sopenharmony_ci cur_limits.rlim_cur = cur_limits.rlim_max = cur_def_msgs * 4098c2ecf20Sopenharmony_ci cur_def_msgsize; 4108c2ecf20Sopenharmony_ci setr(RLIMIT_MSGQUEUE, &cur_limits); 4118c2ecf20Sopenharmony_ci if (test_queue_fail(NULL, &result)) 4128c2ecf20Sopenharmony_ci printf("Kernel creates queue even though defaults " 4138c2ecf20Sopenharmony_ci "would exceed\nrlimit setting:" 4148c2ecf20Sopenharmony_ci "\t\t\t\t\t\t\t\tFAIL\n"); 4158c2ecf20Sopenharmony_ci else 4168c2ecf20Sopenharmony_ci printf("Kernel properly fails to create queue when " 4178c2ecf20Sopenharmony_ci "defaults would\nexceed rlimit:" 4188c2ecf20Sopenharmony_ci "\t\t\t\t\t\t\t\tPASS\n"); 4198c2ecf20Sopenharmony_ci } 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci /* 4228c2ecf20Sopenharmony_ci * Test #2 - open with an attr struct that exceeds rlimit 4238c2ecf20Sopenharmony_ci */ 4248c2ecf20Sopenharmony_ci printf("\n\nTest series 2, behavior when attr struct is " 4258c2ecf20Sopenharmony_ci "passed to mq_open:\n"); 4268c2ecf20Sopenharmony_ci cur_max_msgs = 32; 4278c2ecf20Sopenharmony_ci cur_max_msgsize = cur_limits.rlim_max >> 4; 4288c2ecf20Sopenharmony_ci set(max_msgs, cur_max_msgs); 4298c2ecf20Sopenharmony_ci set(max_msgsize, cur_max_msgsize); 4308c2ecf20Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs; 4318c2ecf20Sopenharmony_ci attr.mq_msgsize = cur_max_msgsize; 4328c2ecf20Sopenharmony_ci if (test_queue_fail(&attr, &result)) 4338c2ecf20Sopenharmony_ci printf("Queue open in excess of rlimit max when euid = 0 " 4348c2ecf20Sopenharmony_ci "succeeded:\t\tFAIL\n"); 4358c2ecf20Sopenharmony_ci else 4368c2ecf20Sopenharmony_ci printf("Queue open in excess of rlimit max when euid = 0 " 4378c2ecf20Sopenharmony_ci "failed:\t\tPASS\n"); 4388c2ecf20Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs + 1; 4398c2ecf20Sopenharmony_ci attr.mq_msgsize = 10; 4408c2ecf20Sopenharmony_ci if (test_queue_fail(&attr, &result)) 4418c2ecf20Sopenharmony_ci printf("Queue open with mq_maxmsg > limit when euid = 0 " 4428c2ecf20Sopenharmony_ci "succeeded:\t\tPASS\n"); 4438c2ecf20Sopenharmony_ci else 4448c2ecf20Sopenharmony_ci printf("Queue open with mq_maxmsg > limit when euid = 0 " 4458c2ecf20Sopenharmony_ci "failed:\t\tFAIL\n"); 4468c2ecf20Sopenharmony_ci attr.mq_maxmsg = 1; 4478c2ecf20Sopenharmony_ci attr.mq_msgsize = cur_max_msgsize + 1; 4488c2ecf20Sopenharmony_ci if (test_queue_fail(&attr, &result)) 4498c2ecf20Sopenharmony_ci printf("Queue open with mq_msgsize > limit when euid = 0 " 4508c2ecf20Sopenharmony_ci "succeeded:\t\tPASS\n"); 4518c2ecf20Sopenharmony_ci else 4528c2ecf20Sopenharmony_ci printf("Queue open with mq_msgsize > limit when euid = 0 " 4538c2ecf20Sopenharmony_ci "failed:\t\tFAIL\n"); 4548c2ecf20Sopenharmony_ci attr.mq_maxmsg = 65536; 4558c2ecf20Sopenharmony_ci attr.mq_msgsize = 65536; 4568c2ecf20Sopenharmony_ci if (test_queue_fail(&attr, &result)) 4578c2ecf20Sopenharmony_ci printf("Queue open with total size > 2GB when euid = 0 " 4588c2ecf20Sopenharmony_ci "succeeded:\t\tFAIL\n"); 4598c2ecf20Sopenharmony_ci else 4608c2ecf20Sopenharmony_ci printf("Queue open with total size > 2GB when euid = 0 " 4618c2ecf20Sopenharmony_ci "failed:\t\t\tPASS\n"); 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (seteuid(99) == -1) { 4648c2ecf20Sopenharmony_ci perror("seteuid() failed"); 4658c2ecf20Sopenharmony_ci exit(1); 4668c2ecf20Sopenharmony_ci } 4678c2ecf20Sopenharmony_ci 4688c2ecf20Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs; 4698c2ecf20Sopenharmony_ci attr.mq_msgsize = cur_max_msgsize; 4708c2ecf20Sopenharmony_ci if (test_queue_fail(&attr, &result)) 4718c2ecf20Sopenharmony_ci printf("Queue open in excess of rlimit max when euid = 99 " 4728c2ecf20Sopenharmony_ci "succeeded:\t\tFAIL\n"); 4738c2ecf20Sopenharmony_ci else 4748c2ecf20Sopenharmony_ci printf("Queue open in excess of rlimit max when euid = 99 " 4758c2ecf20Sopenharmony_ci "failed:\t\tPASS\n"); 4768c2ecf20Sopenharmony_ci attr.mq_maxmsg = cur_max_msgs + 1; 4778c2ecf20Sopenharmony_ci attr.mq_msgsize = 10; 4788c2ecf20Sopenharmony_ci if (test_queue_fail(&attr, &result)) 4798c2ecf20Sopenharmony_ci printf("Queue open with mq_maxmsg > limit when euid = 99 " 4808c2ecf20Sopenharmony_ci "succeeded:\t\tFAIL\n"); 4818c2ecf20Sopenharmony_ci else 4828c2ecf20Sopenharmony_ci printf("Queue open with mq_maxmsg > limit when euid = 99 " 4838c2ecf20Sopenharmony_ci "failed:\t\tPASS\n"); 4848c2ecf20Sopenharmony_ci attr.mq_maxmsg = 1; 4858c2ecf20Sopenharmony_ci attr.mq_msgsize = cur_max_msgsize + 1; 4868c2ecf20Sopenharmony_ci if (test_queue_fail(&attr, &result)) 4878c2ecf20Sopenharmony_ci printf("Queue open with mq_msgsize > limit when euid = 99 " 4888c2ecf20Sopenharmony_ci "succeeded:\t\tFAIL\n"); 4898c2ecf20Sopenharmony_ci else 4908c2ecf20Sopenharmony_ci printf("Queue open with mq_msgsize > limit when euid = 99 " 4918c2ecf20Sopenharmony_ci "failed:\t\tPASS\n"); 4928c2ecf20Sopenharmony_ci attr.mq_maxmsg = 65536; 4938c2ecf20Sopenharmony_ci attr.mq_msgsize = 65536; 4948c2ecf20Sopenharmony_ci if (test_queue_fail(&attr, &result)) 4958c2ecf20Sopenharmony_ci printf("Queue open with total size > 2GB when euid = 99 " 4968c2ecf20Sopenharmony_ci "succeeded:\t\tFAIL\n"); 4978c2ecf20Sopenharmony_ci else 4988c2ecf20Sopenharmony_ci printf("Queue open with total size > 2GB when euid = 99 " 4998c2ecf20Sopenharmony_ci "failed:\t\t\tPASS\n"); 5008c2ecf20Sopenharmony_ci 5018c2ecf20Sopenharmony_ci shutdown(0,"",0); 5028c2ecf20Sopenharmony_ci} 503