1e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin/*
2e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * Check decoding of setreuid/setregid/setreuid32/setregid32 syscalls.
3e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin *
4e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * Copyright (c) 2016 Dmitry V. Levin <ldv@altlinux.org>
5e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * All rights reserved.
6e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin *
7e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * Redistribution and use in source and binary forms, with or without
8e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * modification, are permitted provided that the following conditions
9e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * are met:
10e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * 1. Redistributions of source code must retain the above copyright
11e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin *    notice, this list of conditions and the following disclaimer.
12e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * 2. Redistributions in binary form must reproduce the above copyright
13e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin *    notice, this list of conditions and the following disclaimer in the
14e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin *    documentation and/or other materials provided with the distribution.
15e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * 3. The name of the author may not be used to endorse or promote products
16e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin *    derived from this software without specific prior written permission.
17e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin *
18e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin */
29e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
30e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin#include <errno.h>
31e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin#include <stdio.h>
32e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin#include <unistd.h>
33e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
34e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levinstatic int
35e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levinugid2int(const unsigned UGID_TYPE ugid)
36e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin{
37e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	if ((unsigned UGID_TYPE) -1U == ugid)
38e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		return -1;
39e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	else
40e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		return ugid;
41e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin}
42e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
43e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levinstatic void
44e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levinprint_int(const unsigned int num)
45e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin{
46e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	if (num == -1U)
47e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		printf("-1");
48e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	else
49e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		printf("%u", num);
50e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin}
51e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
52e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levinstatic int
53e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levinnum_matches_id(const unsigned int num, const unsigned int ugid)
54e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin{
55e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	return num == ugid || num == -1U;
56e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin}
57e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
58e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin#define PAIR(val)	{ val, ugid }, { ugid, val }
59e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
60e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levinint
61e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levinmain(void)
62e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin{
63e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	unsigned int ugid = GETUGID;
64e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	CHECK_OVERFLOWUGID(ugid);
65e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
66e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	const struct {
67e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		const long r, e;
68e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	} tests[] = {
69e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		{ ugid, ugid },
70e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		PAIR((unsigned long) 0xffffffff00000000ULL | ugid),
71e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		PAIR(-1U),
72e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		PAIR(-1L),
73e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		PAIR(0xffff0000U | ugid),
74e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		PAIR(0xffff),
75e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		PAIR(0xc0deffffU)
76e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	};
77e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
78e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	unsigned int i;
79e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
80e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	for (i = 0; i < ARRAY_SIZE(tests); ++i) {
81e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		const unsigned int rn = ugid2int(tests[i].r);
82e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		const unsigned int en = ugid2int(tests[i].e);
83e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
84e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		if (!num_matches_id(rn, ugid) || !num_matches_id(en, ugid))
85e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin			continue;
86e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
87e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		if (syscall(SYSCALL_NR, tests[i].r, tests[i].e)) {
88e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin			if (!i && ENOSYS == errno) {
89e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin				printf("%s(%u, %u) = -1 ENOSYS (%m)\n",
90e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin				       SYSCALL_NAME, ugid, ugid);
91e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin				break;
92e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin			}
93e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin			perror_msg_and_fail("%s(%#lx, %#lx)", SYSCALL_NAME,
94e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin					    tests[i].r, tests[i].e);
95e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		}
96e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
97e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		printf("%s(", SYSCALL_NAME);
98e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		print_int(rn);
99e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		printf(", ");
100e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		print_int(en);
101e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin		printf(") = 0\n");
102e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	}
103e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin
104e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	puts("+++ exited with 0 +++");
105e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin	return 0;
106e6d847385050f4ff1de9e10f17875f4e0d30a163Dmitry V. Levin}
107