blob: b51594e0307e3c12cc34ae0d60d935fdaa60f06d [file] [log] [blame]
robbiewa5d67cb2003-01-01 20:44:12 +00001/*
2 * Copyright (c) Wipro Technologies Ltd, 2002. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * You should have received a copy of the GNU General Public License along
Wanlong Gaofed96412012-10-24 10:10:29 +080013 * with this program; if not, write the Free Software Foundation, Inc.,
14 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
robbiewa5d67cb2003-01-01 20:44:12 +000015 *
16 */
17/**********************************************************
subrata_modak4bb656a2009-02-26 12:02:09 +000018 *
robbiewa5d67cb2003-01-01 20:44:12 +000019 * TEST IDENTIFIER : capset02
subrata_modak4bb656a2009-02-26 12:02:09 +000020 *
robbiewa5d67cb2003-01-01 20:44:12 +000021 * EXECUTED BY : anyone
subrata_modak4bb656a2009-02-26 12:02:09 +000022 *
robbiewa5d67cb2003-01-01 20:44:12 +000023 * TEST TITLE : Tests for error conditions.
subrata_modak4bb656a2009-02-26 12:02:09 +000024 *
robbiewa5d67cb2003-01-01 20:44:12 +000025 * TEST CASE TOTAL : 4
subrata_modak4bb656a2009-02-26 12:02:09 +000026 *
robbiewa5d67cb2003-01-01 20:44:12 +000027 * AUTHOR : Saji Kumar.V.R <saji.kumar@wipro.com>
subrata_modak4bb656a2009-02-26 12:02:09 +000028 *
robbiewa5d67cb2003-01-01 20:44:12 +000029 * SIGNALS
30 * Uses SIGUSR1 to pause before test if option set.
31 * (See the parse_opts(3) man page).
32 *
33 * DESCRIPTION
34 * Verify that
35 * 1) capset() fails with errno set to EFAULT if an invalid address
36 * is given for header
37 * 2) capset() fails with errno set to EFAULT if an invalid address
38 * is given for data
39 * 3) capset() fails with errno set to EINVAL if an invalid value
40 * is given for header->version
41 * 4) capset() fails with errno set to EPERM the process does not
42 * have enough privilege to set capabilities
subrata_modakbdbaec52009-02-26 12:14:51 +000043 *
subrata_modak4bb656a2009-02-26 12:02:09 +000044 *
robbiewa5d67cb2003-01-01 20:44:12 +000045 * Setup:
46 * Setup signal handling.
47 * Pause for SIGUSR1 if option specified.
48 * Call capget() to save current capability data
subrata_modak4bb656a2009-02-26 12:02:09 +000049 *
robbiewa5d67cb2003-01-01 20:44:12 +000050 * Test:
51 * Loop if the proper options are given.
52 * do test specific setup.
53 * call capset with proper arguments
54 * if capset() fails with expected errno
55 * Test passed
56 * Otherwise
57 * Test failed
58 * do test specific cleanup
subrata_modak4bb656a2009-02-26 12:02:09 +000059 *
robbiewa5d67cb2003-01-01 20:44:12 +000060 * Cleanup:
61 * Print errno log and/or timing stats if options given
subrata_modak4bb656a2009-02-26 12:02:09 +000062 *
robbiewa5d67cb2003-01-01 20:44:12 +000063 * USAGE: <for command-line>
64 * capset02 [-c n] [-e] [-i n] [-I x] [-P x] [-t] [-h] [-f] [-p]
65 * where, -c n : Run n copies concurrently.
66 * -e : Turn on errno logging.
67 * -h : Show help screen
68 * -f : Turn off functional testing
69 * -i n : Execute test n times.
70 * -I x : Execute test for x seconds.
71 * -p : Pause for SIGUSR1 before starting
72 * -P x : Pause for x seconds between iterations.
73 * -t : Turn on syscall timing.
74 *
75 ****************************************************************/
robbiew267a1d72005-03-21 22:48:56 +000076#include <sys/types.h>
Garrett Coopere499f932010-12-17 11:00:51 -080077#include <sys/wait.h>
78#include <errno.h>
79#include <pwd.h>
robbiew267a1d72005-03-21 22:48:56 +000080#include <signal.h>
Garrett Coopere499f932010-12-17 11:00:51 -080081#include <string.h>
82#include <unistd.h>
robbiewa5d67cb2003-01-01 20:44:12 +000083#include "test.h"
84#include "usctest.h"
Garrett Coopere499f932010-12-17 11:00:51 -080085#include "linux_syscall_numbers.h"
robbiewe7757592003-10-01 17:23:49 +000086
87/**************************************************************************/
robbiewe7757592003-10-01 17:23:49 +000088/* */
89/* Some archs do not have the manpage documented sys/capability.h file, */
robbiew04a8ba52003-10-02 17:38:04 +000090/* and require the use of the line below */
91
92#include <linux/capability.h>
93
94/* If you are having issues with including this file and have the sys/ */
95/* version, then you may want to try switching to it. -Robbie W. */
robbiewe7757592003-10-01 17:23:49 +000096/**************************************************************************/
robbiewa5d67cb2003-01-01 20:44:12 +000097
98#define INVALID_VERSION 0
99
robbiewa5d67cb2003-01-01 20:44:12 +0000100static void setup();
101static void cleanup();
robbiewd34d5812005-07-11 22:28:09 +0000102static void test_setup(int, char *);
103static void child_func();
robbiewa5d67cb2003-01-01 20:44:12 +0000104
robbiew267a1d72005-03-21 22:48:56 +0000105static pid_t child_pid = -1;
106
robbiewa5d67cb2003-01-01 20:44:12 +0000107char *TCID = "capset02"; /* Test program identifier. */
robbiewa5d67cb2003-01-01 20:44:12 +0000108static int exp_enos[] = { EFAULT, EINVAL, EPERM, 0 };
109
110static struct __user_cap_header_struct header;
111static struct __user_cap_data_struct data;
112
113struct test_case_t {
114 cap_user_header_t headerp;
115 cap_user_data_t datap;
116 int exp_errno;
117 char *errdesc;
118} test_cases[] = {
vapier7ec19d92006-02-27 04:38:56 +0000119#ifndef UCLINUX
120 /* Skip since uClinux does not implement memory protection */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800121 {
122 (cap_user_header_t) - 1, &data, EFAULT, "EFAULT"}, {
123 &header, (cap_user_data_t) - 1, EFAULT, "EFAULT"},
vapier7ec19d92006-02-27 04:38:56 +0000124#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800125 {
126 &header, &data, EINVAL, "EINVAL"}, {
127&header, &data, EPERM, "EPERM"},};
robbiewa5d67cb2003-01-01 20:44:12 +0000128
129int TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]);
130
subrata_modak56207ce2009-03-23 13:35:39 +0000131int main(int ac, char **av)
robbiewa5d67cb2003-01-01 20:44:12 +0000132{
133
Garrett Coopere499f932010-12-17 11:00:51 -0800134 int lc, i;
135 char *msg;
robbiewa5d67cb2003-01-01 20:44:12 +0000136
Garrett Cooper53740502010-12-16 00:04:01 -0800137 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800138 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
robbiewd34d5812005-07-11 22:28:09 +0000139#ifdef UCLINUX
140 maybe_run_child(&child_func, "");
141#endif
142
robbiewa5d67cb2003-01-01 20:44:12 +0000143 setup();
144
robbiewa5d67cb2003-01-01 20:44:12 +0000145 for (lc = 0; TEST_LOOPING(lc); lc++) {
146
robbiewa5d67cb2003-01-01 20:44:12 +0000147 Tst_count = 0;
148
Garrett Coopere499f932010-12-17 11:00:51 -0800149#ifdef UCLINUX
150 i = 2;
151#else
152 i = 0;
153#endif
154
Wanlong Gao354ebb42012-12-07 10:10:04 +0800155 for (; i < TST_TOTAL; i++) {
robbiewa5d67cb2003-01-01 20:44:12 +0000156
robbiewd34d5812005-07-11 22:28:09 +0000157 test_setup(i, av[0]);
Jan Stancek359980f2013-02-15 10:16:05 +0100158 TEST(ltp_syscall(__NR_capset, test_cases[i].headerp,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800159 test_cases[i].datap));
robbiewa5d67cb2003-01-01 20:44:12 +0000160
Garrett Coopere499f932010-12-17 11:00:51 -0800161 if (TEST_RETURN == -1 &&
162 TEST_ERRNO == test_cases[i].exp_errno) {
robbiewa5d67cb2003-01-01 20:44:12 +0000163 tst_resm(TPASS, "capset() returned -1,"
subrata_modak56207ce2009-03-23 13:35:39 +0000164 " errno: %s", test_cases[i].errdesc);
robbiewa5d67cb2003-01-01 20:44:12 +0000165 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800166 tst_resm(TFAIL | TTERRNO,
167 "Test Failed, capset() returned %ld",
168 TEST_RETURN);
robbiewa5d67cb2003-01-01 20:44:12 +0000169 }
subrata_modak4bb656a2009-02-26 12:02:09 +0000170 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800171 }
robbiewa5d67cb2003-01-01 20:44:12 +0000172
robbiewa5d67cb2003-01-01 20:44:12 +0000173 cleanup();
174
Garrett Cooper53740502010-12-16 00:04:01 -0800175 tst_exit();
robbiewa5d67cb2003-01-01 20:44:12 +0000176
Garrett Cooper2c282152010-12-16 00:55:50 -0800177}
robbiewa5d67cb2003-01-01 20:44:12 +0000178
subrata_modak56207ce2009-03-23 13:35:39 +0000179void setup()
robbiewa5d67cb2003-01-01 20:44:12 +0000180{
181
robbiewa5d67cb2003-01-01 20:44:12 +0000182 TEST_EXP_ENOS(exp_enos);
183
robbiewa5d67cb2003-01-01 20:44:12 +0000184 TEST_PAUSE;
185
186 /*
187 * Save current capability data.
188 * header.version must be _LINUX_CAPABILITY_VERSION
189 */
190 header.version = _LINUX_CAPABILITY_VERSION;
Jan Stancek359980f2013-02-15 10:16:05 +0100191 if (ltp_syscall(__NR_capget, &header, &data) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800192 tst_brkm(TBROK | TERRNO, NULL, "capget failed");
Garrett Cooper2c282152010-12-16 00:55:50 -0800193}
robbiewa5d67cb2003-01-01 20:44:12 +0000194
subrata_modak56207ce2009-03-23 13:35:39 +0000195void cleanup()
robbiewa5d67cb2003-01-01 20:44:12 +0000196{
Garrett Coopere499f932010-12-17 11:00:51 -0800197 if (0 < child_pid) {
subrata_modak56207ce2009-03-23 13:35:39 +0000198 kill(child_pid, SIGTERM);
Garrett Coopere499f932010-12-17 11:00:51 -0800199 wait(NULL);
200 }
robbiewa5d67cb2003-01-01 20:44:12 +0000201 TEST_CLEANUP;
Garrett Cooper2c282152010-12-16 00:55:50 -0800202}
robbiewa5d67cb2003-01-01 20:44:12 +0000203
robbiew267a1d72005-03-21 22:48:56 +0000204void child_func()
205{
subrata_modak56207ce2009-03-23 13:35:39 +0000206 for (;;) {
207 sleep(10);
208 }
robbiew267a1d72005-03-21 22:48:56 +0000209}
210
subrata_modak56207ce2009-03-23 13:35:39 +0000211void test_setup(int i, char *argv0)
robbiewa5d67cb2003-01-01 20:44:12 +0000212{
robbiew9b0da822005-10-04 16:28:39 +0000213 char nobody_uid[] = "nobody";
214 struct passwd *ltpuser;
215
robbiewa5d67cb2003-01-01 20:44:12 +0000216 switch (i) {
subrata_modak56207ce2009-03-23 13:35:39 +0000217 case 0:
robbiewa5d67cb2003-01-01 20:44:12 +0000218 break;
219
subrata_modak56207ce2009-03-23 13:35:39 +0000220 case 1:
robbiewa5d67cb2003-01-01 20:44:12 +0000221 header.version = _LINUX_CAPABILITY_VERSION;
222 header.pid = 0;
223 break;
224
subrata_modak56207ce2009-03-23 13:35:39 +0000225 case 2:
robbiewa5d67cb2003-01-01 20:44:12 +0000226 header.version = INVALID_VERSION;
227 header.pid = 0;
228 break;
229
subrata_modak56207ce2009-03-23 13:35:39 +0000230 case 3:
robbiewa5d67cb2003-01-01 20:44:12 +0000231 header.version = _LINUX_CAPABILITY_VERSION;
232 /*
233 * when a non-zero pid is specified, process should have
234 * CAP_SETPCAP capability to change capabilities.
235 * by default, CAP_SETPCAP is not enabled. So giving
236 * a non-zero pid results in capset() failing with
237 * errno EPERM
subrata_modak4bb656a2009-02-26 12:02:09 +0000238 *
robbiew267a1d72005-03-21 22:48:56 +0000239 * Note: this seems to have changed with recent kernels
240 * => create a child and try to set its capabilities
robbiewa5d67cb2003-01-01 20:44:12 +0000241 */
robbiewd34d5812005-07-11 22:28:09 +0000242 child_pid = FORK_OR_VFORK();
Garrett Coopere499f932010-12-17 11:00:51 -0800243 if (child_pid == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800244 tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
Garrett Coopere499f932010-12-17 11:00:51 -0800245 else if (child_pid == 0) {
robbiewd34d5812005-07-11 22:28:09 +0000246#ifdef UCLINUX
247 if (self_exec(argv0, "") < 0) {
Garrett Coopere499f932010-12-17 11:00:51 -0800248 perror("self_exec failed");
249 exit(1);
robbiewd34d5812005-07-11 22:28:09 +0000250 }
251#else
robbiew267a1d72005-03-21 22:48:56 +0000252 child_func();
robbiewd34d5812005-07-11 22:28:09 +0000253#endif
Garrett Coopere499f932010-12-17 11:00:51 -0800254 } else {
robbiew267a1d72005-03-21 22:48:56 +0000255 header.pid = child_pid;
robbiew9b0da822005-10-04 16:28:39 +0000256 ltpuser = getpwnam(nobody_uid);
Garrett Coopere499f932010-12-17 11:00:51 -0800257 if (ltpuser == NULL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800258 tst_brkm(TBROK | TERRNO, cleanup,
259 "getpwnam failed");
Garrett Coopere499f932010-12-17 11:00:51 -0800260 if (seteuid(ltpuser->pw_uid) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800261 tst_brkm(TBROK | TERRNO, cleanup,
262 "seteuid failed");
robbiew9b0da822005-10-04 16:28:39 +0000263
robbiew267a1d72005-03-21 22:48:56 +0000264 }
robbiewa5d67cb2003-01-01 20:44:12 +0000265 break;
266
267 }
Chris Dearmanec6edca2012-10-17 19:54:01 -0700268}