139bac055674d23770b9a724221b728e443196ea7Elliott Hughes/*
239bac055674d23770b9a724221b728e443196ea7Elliott Hughes * Check decoding of sigsuspend syscall.
339bac055674d23770b9a724221b728e443196ea7Elliott Hughes *
439bac055674d23770b9a724221b728e443196ea7Elliott Hughes * Copyright (c) 2017 Dmitry V. Levin <ldv@altlinux.org>
539bac055674d23770b9a724221b728e443196ea7Elliott Hughes * All rights reserved.
639bac055674d23770b9a724221b728e443196ea7Elliott Hughes *
739bac055674d23770b9a724221b728e443196ea7Elliott Hughes * Redistribution and use in source and binary forms, with or without
839bac055674d23770b9a724221b728e443196ea7Elliott Hughes * modification, are permitted provided that the following conditions
939bac055674d23770b9a724221b728e443196ea7Elliott Hughes * are met:
1039bac055674d23770b9a724221b728e443196ea7Elliott Hughes * 1. Redistributions of source code must retain the above copyright
1139bac055674d23770b9a724221b728e443196ea7Elliott Hughes *    notice, this list of conditions and the following disclaimer.
1239bac055674d23770b9a724221b728e443196ea7Elliott Hughes * 2. Redistributions in binary form must reproduce the above copyright
1339bac055674d23770b9a724221b728e443196ea7Elliott Hughes *    notice, this list of conditions and the following disclaimer in the
1439bac055674d23770b9a724221b728e443196ea7Elliott Hughes *    documentation and/or other materials provided with the distribution.
1539bac055674d23770b9a724221b728e443196ea7Elliott Hughes * 3. The name of the author may not be used to endorse or promote products
1639bac055674d23770b9a724221b728e443196ea7Elliott Hughes *    derived from this software without specific prior written permission.
1739bac055674d23770b9a724221b728e443196ea7Elliott Hughes *
1839bac055674d23770b9a724221b728e443196ea7Elliott Hughes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1939bac055674d23770b9a724221b728e443196ea7Elliott Hughes * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2039bac055674d23770b9a724221b728e443196ea7Elliott Hughes * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
2139bac055674d23770b9a724221b728e443196ea7Elliott Hughes * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
2239bac055674d23770b9a724221b728e443196ea7Elliott Hughes * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2339bac055674d23770b9a724221b728e443196ea7Elliott Hughes * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2439bac055674d23770b9a724221b728e443196ea7Elliott Hughes * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2539bac055674d23770b9a724221b728e443196ea7Elliott Hughes * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2639bac055674d23770b9a724221b728e443196ea7Elliott Hughes * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2739bac055674d23770b9a724221b728e443196ea7Elliott Hughes * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2839bac055674d23770b9a724221b728e443196ea7Elliott Hughes */
2939bac055674d23770b9a724221b728e443196ea7Elliott Hughes
3039bac055674d23770b9a724221b728e443196ea7Elliott Hughes#include "tests.h"
3139bac055674d23770b9a724221b728e443196ea7Elliott Hughes#include <asm/unistd.h>
3239bac055674d23770b9a724221b728e443196ea7Elliott Hughes
3339bac055674d23770b9a724221b728e443196ea7Elliott Hughes#ifdef __NR_sigsuspend
3439bac055674d23770b9a724221b728e443196ea7Elliott Hughes
3539bac055674d23770b9a724221b728e443196ea7Elliott Hughes# include <assert.h>
3639bac055674d23770b9a724221b728e443196ea7Elliott Hughes# include <errno.h>
3739bac055674d23770b9a724221b728e443196ea7Elliott Hughes# include <signal.h>
3839bac055674d23770b9a724221b728e443196ea7Elliott Hughes# include <stdio.h>
3939bac055674d23770b9a724221b728e443196ea7Elliott Hughes# include <stdint.h>
4039bac055674d23770b9a724221b728e443196ea7Elliott Hughes# include <string.h>
4139bac055674d23770b9a724221b728e443196ea7Elliott Hughes# include <unistd.h>
4239bac055674d23770b9a724221b728e443196ea7Elliott Hughes
4339bac055674d23770b9a724221b728e443196ea7Elliott Hughes# ifdef MIPS
4439bac055674d23770b9a724221b728e443196ea7Elliott Hughes#  define SIGNAL_MASK_BY_REF 1
4539bac055674d23770b9a724221b728e443196ea7Elliott Hughes# else
4639bac055674d23770b9a724221b728e443196ea7Elliott Hughes#  define SIGNAL_MASK_BY_REF 0
4739bac055674d23770b9a724221b728e443196ea7Elliott Hughes# endif
4839bac055674d23770b9a724221b728e443196ea7Elliott Hughes
4939bac055674d23770b9a724221b728e443196ea7Elliott Hughesstatic long
5039bac055674d23770b9a724221b728e443196ea7Elliott Hughesk_sigsuspend(const kernel_ulong_t arg1,
5139bac055674d23770b9a724221b728e443196ea7Elliott Hughes	     const kernel_ulong_t arg2,
5239bac055674d23770b9a724221b728e443196ea7Elliott Hughes	     const kernel_ulong_t arg3)
5339bac055674d23770b9a724221b728e443196ea7Elliott Hughes{
5439bac055674d23770b9a724221b728e443196ea7Elliott Hughes	return syscall(__NR_sigsuspend, arg1, arg2, arg3);
5539bac055674d23770b9a724221b728e443196ea7Elliott Hughes}
5639bac055674d23770b9a724221b728e443196ea7Elliott Hughes
5739bac055674d23770b9a724221b728e443196ea7Elliott Hughesstatic int signo;
5839bac055674d23770b9a724221b728e443196ea7Elliott Hughesstatic const char *sigtxt[] = {
5939bac055674d23770b9a724221b728e443196ea7Elliott Hughes	[SIGUSR1] = "USR1",
6039bac055674d23770b9a724221b728e443196ea7Elliott Hughes	[SIGUSR2] = "USR2"
6139bac055674d23770b9a724221b728e443196ea7Elliott Hughes};
6239bac055674d23770b9a724221b728e443196ea7Elliott Hughes
6339bac055674d23770b9a724221b728e443196ea7Elliott Hughesstatic void
6439bac055674d23770b9a724221b728e443196ea7Elliott Hugheshandler(int i)
6539bac055674d23770b9a724221b728e443196ea7Elliott Hughes{
6639bac055674d23770b9a724221b728e443196ea7Elliott Hughes	signo = i;
6739bac055674d23770b9a724221b728e443196ea7Elliott Hughes}
6839bac055674d23770b9a724221b728e443196ea7Elliott Hughes
6939bac055674d23770b9a724221b728e443196ea7Elliott Hughesint
7039bac055674d23770b9a724221b728e443196ea7Elliott Hughesmain(void)
7139bac055674d23770b9a724221b728e443196ea7Elliott Hughes{
7239bac055674d23770b9a724221b728e443196ea7Elliott Hughes	union {
7339bac055674d23770b9a724221b728e443196ea7Elliott Hughes		sigset_t libc_mask;
7439bac055674d23770b9a724221b728e443196ea7Elliott Hughes		unsigned long old_mask;
7539bac055674d23770b9a724221b728e443196ea7Elliott Hughes	} u;
7639bac055674d23770b9a724221b728e443196ea7Elliott Hughes
7739bac055674d23770b9a724221b728e443196ea7Elliott Hughes	sigemptyset(&u.libc_mask);
7839bac055674d23770b9a724221b728e443196ea7Elliott Hughes	sigaddset(&u.libc_mask, SIGUSR1);
7939bac055674d23770b9a724221b728e443196ea7Elliott Hughes	sigaddset(&u.libc_mask, SIGUSR2);
8039bac055674d23770b9a724221b728e443196ea7Elliott Hughes	if (sigprocmask(SIG_SETMASK, &u.libc_mask, NULL))
8139bac055674d23770b9a724221b728e443196ea7Elliott Hughes		perror_msg_and_fail("sigprocmask");
8239bac055674d23770b9a724221b728e443196ea7Elliott Hughes
8339bac055674d23770b9a724221b728e443196ea7Elliott Hughes	const struct sigaction sa = { .sa_handler = handler };
8439bac055674d23770b9a724221b728e443196ea7Elliott Hughes	if (sigaction(SIGUSR1, &sa, NULL) || sigaction(SIGUSR2, &sa, NULL))
8539bac055674d23770b9a724221b728e443196ea7Elliott Hughes		perror_msg_and_fail("sigaction");
8639bac055674d23770b9a724221b728e443196ea7Elliott Hughes
8739bac055674d23770b9a724221b728e443196ea7Elliott Hughes	raise(SIGUSR1);
8839bac055674d23770b9a724221b728e443196ea7Elliott Hughes	raise(SIGUSR2);
8939bac055674d23770b9a724221b728e443196ea7Elliott Hughes
9039bac055674d23770b9a724221b728e443196ea7Elliott Hughes	u.old_mask = -1UL;
9139bac055674d23770b9a724221b728e443196ea7Elliott Hughes	sigdelset(&u.libc_mask, SIGUSR1);
9239bac055674d23770b9a724221b728e443196ea7Elliott Hughes	const unsigned long mask1 = u.old_mask;
9339bac055674d23770b9a724221b728e443196ea7Elliott Hughes
9439bac055674d23770b9a724221b728e443196ea7Elliott Hughes	u.old_mask = -1UL;
9539bac055674d23770b9a724221b728e443196ea7Elliott Hughes	sigdelset(&u.libc_mask, SIGUSR2);
9639bac055674d23770b9a724221b728e443196ea7Elliott Hughes	const unsigned long mask2 = u.old_mask;
9739bac055674d23770b9a724221b728e443196ea7Elliott Hughes
9839bac055674d23770b9a724221b728e443196ea7Elliott Hughes#if SIGNAL_MASK_BY_REF
9939bac055674d23770b9a724221b728e443196ea7Elliott Hughes	k_sigsuspend((uintptr_t) &mask1, 0xdeadbeef, (uintptr_t) &mask2);
10039bac055674d23770b9a724221b728e443196ea7Elliott Hughes#else
10139bac055674d23770b9a724221b728e443196ea7Elliott Hughes	k_sigsuspend(mask1, 0xdeadbeef, mask2);
10239bac055674d23770b9a724221b728e443196ea7Elliott Hughes#endif
10339bac055674d23770b9a724221b728e443196ea7Elliott Hughes	if (EINTR != errno)
10439bac055674d23770b9a724221b728e443196ea7Elliott Hughes		perror_msg_and_skip("sigsuspend");
10539bac055674d23770b9a724221b728e443196ea7Elliott Hughes
10639bac055674d23770b9a724221b728e443196ea7Elliott Hughes	printf("sigsuspend(~[%s]) = ? ERESTARTNOHAND"
10739bac055674d23770b9a724221b728e443196ea7Elliott Hughes	       " (To be restarted if no handler)\n", sigtxt[signo]);
10839bac055674d23770b9a724221b728e443196ea7Elliott Hughes
10939bac055674d23770b9a724221b728e443196ea7Elliott Hughes	puts("+++ exited with 0 +++");
11039bac055674d23770b9a724221b728e443196ea7Elliott Hughes	return 0;
11139bac055674d23770b9a724221b728e443196ea7Elliott Hughes}
11239bac055674d23770b9a724221b728e443196ea7Elliott Hughes
11339bac055674d23770b9a724221b728e443196ea7Elliott Hughes#else
11439bac055674d23770b9a724221b728e443196ea7Elliott Hughes
11539bac055674d23770b9a724221b728e443196ea7Elliott HughesSKIP_MAIN_UNDEFINED("__NR_sigsuspend")
11639bac055674d23770b9a724221b728e443196ea7Elliott Hughes
11739bac055674d23770b9a724221b728e443196ea7Elliott Hughes#endif
118