blob: 411d35ca6f87f1640de048824252ce1eba5e7901 [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"
Garrett Coopere499f932010-12-17 11:00:51 -080084#include "linux_syscall_numbers.h"
robbiewe7757592003-10-01 17:23:49 +000085
86/**************************************************************************/
robbiewe7757592003-10-01 17:23:49 +000087/* */
88/* Some archs do not have the manpage documented sys/capability.h file, */
robbiew04a8ba52003-10-02 17:38:04 +000089/* and require the use of the line below */
90
91#include <linux/capability.h>
92
93/* If you are having issues with including this file and have the sys/ */
94/* version, then you may want to try switching to it. -Robbie W. */
robbiewe7757592003-10-01 17:23:49 +000095/**************************************************************************/
robbiewa5d67cb2003-01-01 20:44:12 +000096
97#define INVALID_VERSION 0
98
Mike Frysingerc57fba52014-04-09 18:56:30 -040099static void setup(void);
100static void cleanup(void);
robbiewd34d5812005-07-11 22:28:09 +0000101static void test_setup(int, char *);
Mike Frysingerc57fba52014-04-09 18:56:30 -0400102static void child_func(void);
robbiewa5d67cb2003-01-01 20:44:12 +0000103
robbiew267a1d72005-03-21 22:48:56 +0000104static pid_t child_pid = -1;
105
Cyril Hrubisfdce7d52013-04-04 18:35:48 +0200106char *TCID = "capset02";
robbiewa5d67cb2003-01-01 20:44:12 +0000107
108static struct __user_cap_header_struct header;
109static struct __user_cap_data_struct data;
110
111struct test_case_t {
112 cap_user_header_t headerp;
113 cap_user_data_t datap;
114 int exp_errno;
115 char *errdesc;
116} test_cases[] = {
vapier7ec19d92006-02-27 04:38:56 +0000117#ifndef UCLINUX
118 /* Skip since uClinux does not implement memory protection */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800119 {
120 (cap_user_header_t) - 1, &data, EFAULT, "EFAULT"}, {
121 &header, (cap_user_data_t) - 1, EFAULT, "EFAULT"},
vapier7ec19d92006-02-27 04:38:56 +0000122#endif
Wanlong Gao354ebb42012-12-07 10:10:04 +0800123 {
124 &header, &data, EINVAL, "EINVAL"}, {
125&header, &data, EPERM, "EPERM"},};
robbiewa5d67cb2003-01-01 20:44:12 +0000126
127int TST_TOTAL = sizeof(test_cases) / sizeof(test_cases[0]);
128
subrata_modak56207ce2009-03-23 13:35:39 +0000129int main(int ac, char **av)
robbiewa5d67cb2003-01-01 20:44:12 +0000130{
131
Garrett Coopere499f932010-12-17 11:00:51 -0800132 int lc, i;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200133 const char *msg;
robbiewa5d67cb2003-01-01 20:44:12 +0000134
Garrett Cooper53740502010-12-16 00:04:01 -0800135 if ((msg = parse_opts(ac, av, NULL, NULL)) != NULL)
Garrett Cooper60fa8012010-11-22 13:50:58 -0800136 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
robbiewd34d5812005-07-11 22:28:09 +0000137#ifdef UCLINUX
138 maybe_run_child(&child_func, "");
139#endif
140
robbiewa5d67cb2003-01-01 20:44:12 +0000141 setup();
142
robbiewa5d67cb2003-01-01 20:44:12 +0000143 for (lc = 0; TEST_LOOPING(lc); lc++) {
144
Caspar Zhangd59a6592013-03-07 14:59:12 +0800145 tst_count = 0;
robbiewa5d67cb2003-01-01 20:44:12 +0000146
Garrett Coopere499f932010-12-17 11:00:51 -0800147#ifdef UCLINUX
148 i = 2;
149#else
150 i = 0;
151#endif
152
Wanlong Gao354ebb42012-12-07 10:10:04 +0800153 for (; i < TST_TOTAL; i++) {
robbiewa5d67cb2003-01-01 20:44:12 +0000154
robbiewd34d5812005-07-11 22:28:09 +0000155 test_setup(i, av[0]);
Jan Stancek359980f2013-02-15 10:16:05 +0100156 TEST(ltp_syscall(__NR_capset, test_cases[i].headerp,
Wanlong Gao354ebb42012-12-07 10:10:04 +0800157 test_cases[i].datap));
robbiewa5d67cb2003-01-01 20:44:12 +0000158
Garrett Coopere499f932010-12-17 11:00:51 -0800159 if (TEST_RETURN == -1 &&
160 TEST_ERRNO == test_cases[i].exp_errno) {
robbiewa5d67cb2003-01-01 20:44:12 +0000161 tst_resm(TPASS, "capset() returned -1,"
subrata_modak56207ce2009-03-23 13:35:39 +0000162 " errno: %s", test_cases[i].errdesc);
robbiewa5d67cb2003-01-01 20:44:12 +0000163 } else {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800164 tst_resm(TFAIL | TTERRNO,
165 "Test Failed, capset() returned %ld",
166 TEST_RETURN);
robbiewa5d67cb2003-01-01 20:44:12 +0000167 }
subrata_modak4bb656a2009-02-26 12:02:09 +0000168 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800169 }
robbiewa5d67cb2003-01-01 20:44:12 +0000170
robbiewa5d67cb2003-01-01 20:44:12 +0000171 cleanup();
172
Garrett Cooper53740502010-12-16 00:04:01 -0800173 tst_exit();
robbiewa5d67cb2003-01-01 20:44:12 +0000174
Garrett Cooper2c282152010-12-16 00:55:50 -0800175}
robbiewa5d67cb2003-01-01 20:44:12 +0000176
Mike Frysingerc57fba52014-04-09 18:56:30 -0400177void setup(void)
robbiewa5d67cb2003-01-01 20:44:12 +0000178{
179
robbiewa5d67cb2003-01-01 20:44:12 +0000180 TEST_PAUSE;
181
182 /*
183 * Save current capability data.
184 * header.version must be _LINUX_CAPABILITY_VERSION
185 */
186 header.version = _LINUX_CAPABILITY_VERSION;
Jan Stancek359980f2013-02-15 10:16:05 +0100187 if (ltp_syscall(__NR_capget, &header, &data) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800188 tst_brkm(TBROK | TERRNO, NULL, "capget failed");
Garrett Cooper2c282152010-12-16 00:55:50 -0800189}
robbiewa5d67cb2003-01-01 20:44:12 +0000190
Mike Frysingerc57fba52014-04-09 18:56:30 -0400191void cleanup(void)
robbiewa5d67cb2003-01-01 20:44:12 +0000192{
Garrett Coopere499f932010-12-17 11:00:51 -0800193 if (0 < child_pid) {
subrata_modak56207ce2009-03-23 13:35:39 +0000194 kill(child_pid, SIGTERM);
Garrett Coopere499f932010-12-17 11:00:51 -0800195 wait(NULL);
196 }
Garrett Cooper2c282152010-12-16 00:55:50 -0800197}
robbiewa5d67cb2003-01-01 20:44:12 +0000198
Mike Frysingerc57fba52014-04-09 18:56:30 -0400199void child_func(void)
robbiew267a1d72005-03-21 22:48:56 +0000200{
subrata_modak56207ce2009-03-23 13:35:39 +0000201 for (;;) {
202 sleep(10);
203 }
robbiew267a1d72005-03-21 22:48:56 +0000204}
205
subrata_modak56207ce2009-03-23 13:35:39 +0000206void test_setup(int i, char *argv0)
robbiewa5d67cb2003-01-01 20:44:12 +0000207{
robbiew9b0da822005-10-04 16:28:39 +0000208 char nobody_uid[] = "nobody";
209 struct passwd *ltpuser;
210
robbiewa5d67cb2003-01-01 20:44:12 +0000211 switch (i) {
subrata_modak56207ce2009-03-23 13:35:39 +0000212 case 0:
robbiewa5d67cb2003-01-01 20:44:12 +0000213 break;
214
subrata_modak56207ce2009-03-23 13:35:39 +0000215 case 1:
robbiewa5d67cb2003-01-01 20:44:12 +0000216 header.version = _LINUX_CAPABILITY_VERSION;
217 header.pid = 0;
218 break;
219
subrata_modak56207ce2009-03-23 13:35:39 +0000220 case 2:
robbiewa5d67cb2003-01-01 20:44:12 +0000221 header.version = INVALID_VERSION;
222 header.pid = 0;
223 break;
224
subrata_modak56207ce2009-03-23 13:35:39 +0000225 case 3:
robbiewa5d67cb2003-01-01 20:44:12 +0000226 header.version = _LINUX_CAPABILITY_VERSION;
227 /*
228 * when a non-zero pid is specified, process should have
229 * CAP_SETPCAP capability to change capabilities.
230 * by default, CAP_SETPCAP is not enabled. So giving
231 * a non-zero pid results in capset() failing with
232 * errno EPERM
subrata_modak4bb656a2009-02-26 12:02:09 +0000233 *
robbiew267a1d72005-03-21 22:48:56 +0000234 * Note: this seems to have changed with recent kernels
235 * => create a child and try to set its capabilities
robbiewa5d67cb2003-01-01 20:44:12 +0000236 */
robbiewd34d5812005-07-11 22:28:09 +0000237 child_pid = FORK_OR_VFORK();
Garrett Coopere499f932010-12-17 11:00:51 -0800238 if (child_pid == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800239 tst_brkm(TBROK | TERRNO, cleanup, "fork failed");
Garrett Coopere499f932010-12-17 11:00:51 -0800240 else if (child_pid == 0) {
robbiewd34d5812005-07-11 22:28:09 +0000241#ifdef UCLINUX
242 if (self_exec(argv0, "") < 0) {
Garrett Coopere499f932010-12-17 11:00:51 -0800243 perror("self_exec failed");
244 exit(1);
robbiewd34d5812005-07-11 22:28:09 +0000245 }
246#else
robbiew267a1d72005-03-21 22:48:56 +0000247 child_func();
robbiewd34d5812005-07-11 22:28:09 +0000248#endif
Garrett Coopere499f932010-12-17 11:00:51 -0800249 } else {
robbiew267a1d72005-03-21 22:48:56 +0000250 header.pid = child_pid;
robbiew9b0da822005-10-04 16:28:39 +0000251 ltpuser = getpwnam(nobody_uid);
Garrett Coopere499f932010-12-17 11:00:51 -0800252 if (ltpuser == NULL)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800253 tst_brkm(TBROK | TERRNO, cleanup,
254 "getpwnam failed");
Garrett Coopere499f932010-12-17 11:00:51 -0800255 if (seteuid(ltpuser->pw_uid) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800256 tst_brkm(TBROK | TERRNO, cleanup,
257 "seteuid failed");
robbiew9b0da822005-10-04 16:28:39 +0000258
robbiew267a1d72005-03-21 22:48:56 +0000259 }
robbiewa5d67cb2003-01-01 20:44:12 +0000260 break;
261
262 }
Chris Dearmanec6edca2012-10-17 19:54:01 -0700263}