iconv: Suppress array out of bounds warning.
[platform/upstream/glibc.git] / nptl / tst-setuid2.c
1 /* Copyright (C) 2014-2015 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <http://www.gnu.org/licenses/>.  */
17
18 #include <errno.h>
19 #include <pthread.h>
20 #include <signal.h>
21 #include <stdbool.h>
22 #include <stdio.h>
23 #include <sys/syscall.h>
24 #include <unistd.h>
25
26 /* Check that a partial setuid failure aborts the process. */
27
28 static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
29 static pthread_cond_t cond_send;
30 static void (*func_sent) (void);
31 static pthread_cond_t cond_recv;
32
33 #define FAIL(fmt, ...) \
34   do { printf ("FAIL: " fmt "\n", __VA_ARGS__); _exit (1); } while (0)
35
36 static void *
37 thread_func (void *ctx __attribute__ ((unused)))
38 {
39   int ret = pthread_mutex_lock (&mutex);
40   if (ret != 0)
41     FAIL ("pthread_mutex_lock (thread): %d", ret);
42
43   while (true)
44     {
45       if (func_sent != NULL)
46         {
47           void (*func) (void) = func_sent;
48           ret = pthread_mutex_unlock (&mutex);
49           if (ret != 0)
50             FAIL ("pthread_mutex_unlock (thread): %d", ret);
51           func ();
52           ret = pthread_mutex_lock (&mutex);
53           if (ret != 0)
54             FAIL ("pthread_mutex_lock (thread): %d", ret);
55           func_sent = NULL;
56           ret = pthread_cond_signal (&cond_recv);
57           if (ret != 0)
58             FAIL ("pthread_cond_signal (recv): %d", ret);
59         }
60       ret = pthread_cond_wait (&cond_send, &mutex);
61       if (ret != 0)
62         FAIL ("pthread_cond_wait (send): %d", ret);
63     }
64   return NULL;
65 }
66
67 static void
68 run_on_thread (void (*func) (void))
69 {
70   int ret = pthread_mutex_lock (&mutex);
71   if (ret != 0)
72     FAIL ("pthread_mutex_lock (%s): %d", __func__, ret);
73   func_sent = func;
74   ret = pthread_mutex_unlock (&mutex);
75   if (ret != 0)
76     FAIL ("pthread_mutex_unlock (%s): %d", __func__, ret);
77
78   ret = pthread_cond_signal (&cond_send);
79   if (ret != 0)
80     FAIL ("pthread_mutex_lock (%s): %d", __func__, ret);
81
82   ret = pthread_mutex_lock (&mutex);
83   if (ret != 0)
84     FAIL ("pthread_mutex_lock (%s): %d", __func__, ret);
85
86   while (func_sent != NULL)
87     {
88       ret = pthread_cond_wait (&cond_recv, &mutex);
89       if (ret != 0)
90         FAIL ("pthread_mutex_wait (%s): %d", __func__, ret);
91     }
92   ret = pthread_mutex_unlock (&mutex);
93   if (ret != 0)
94     FAIL ("pthread_mutex_unlock (%s): %d", __func__, ret);
95 }
96
97 static void
98 change_thread_ids (void)
99 {
100   long ret = syscall (__NR_setresuid, 2001, 2002, 2003);
101   if (ret != 0)
102     FAIL ("setresuid (2001, 2002, 2003): %ld", ret);
103 }
104
105 static uid_t ruid, euid, suid;
106
107 static void
108 get_thread_ids (void)
109 {
110   if (getresuid (&ruid, &euid, &suid) < 0)
111     FAIL ("getresuid: %m (%d)", errno);
112 }
113
114 static void
115 abort_expected (int signal __attribute__ ((unused)))
116 {
117   _exit (0);
118 }
119
120 static int
121 do_test (void)
122 {
123   pthread_t thread;
124   int ret = pthread_create (&thread, NULL, thread_func, NULL);
125   if (ret != 0)
126     FAIL ("pthread_create: %d", ret);
127
128   run_on_thread (change_thread_ids);
129
130   signal (SIGABRT, &abort_expected);
131   /* This should abort the process.  */
132   if (setresuid (1001, 1002, 1003) < 0)
133     FAIL ("setresuid: %m (%d)", errno);
134   signal (SIGABRT, SIG_DFL);
135
136   /* If we get here, check that the kernel did the right thing. */
137   run_on_thread (get_thread_ids);
138   if (ruid != 1001 || euid != 1002 || suid != 1003)
139     FAIL ("unexpected UIDs after setuid: %ld, %ld, %ld",
140           (long) ruid, (long) euid, (long) suid);
141   return 0;
142 }
143
144 #define TEST_FUNCTION do_test ()
145 #include "../test-skeleton.c"