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