Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/tools/regression/security/cap_test/cap_test_relative.c
48266 views
1
/*-
2
* Copyright (c) 2009-2011 Robert N. M. Watson
3
* Copyright (c) 2011 Jonathan Anderson
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
* 1. Redistributions of source code must retain the above copyright
10
* notice, this list of conditions and the following disclaimer.
11
* 2. Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
* SUCH DAMAGE.
26
*/
27
28
#include <sys/param.h>
29
#include <sys/capsicum.h>
30
#include <sys/errno.h>
31
32
#include <err.h>
33
#include <fcntl.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <unistd.h>
37
38
#include "cap_test.h"
39
40
/*
41
* Test openat(2) in a variety of sitations to ensure that it obeys Capsicum
42
* "strict relative" rules:
43
*
44
* 1. Use strict relative lookups in capability mode or when operating
45
* relative to a capability.
46
* 2. When performing strict relative lookups, absolute paths (including
47
* symlinks to absolute paths) are not allowed, nor are paths containing
48
* '..' components.
49
*/
50
int
51
test_relative(void)
52
{
53
int success = PASSED;
54
int fd, etc, etc_cap, etc_cap_ro, etc_cap_base, etc_cap_all;
55
cap_rights_t baserights = CAP_READ | CAP_WRITE | CAP_SEEK | CAP_LOOKUP;
56
cap_rights_t rights;
57
58
REQUIRE(etc = open("/etc/", O_RDONLY));
59
CHECK_SYSCALL_SUCCEEDS(cap_getrights, etc, &rights);
60
CHECK_RIGHTS(rights, CAP_ALL);
61
62
MAKE_CAPABILITY(etc_cap, etc, CAP_READ);
63
MAKE_CAPABILITY(etc_cap_ro, etc, CAP_READ | CAP_LOOKUP);
64
MAKE_CAPABILITY(etc_cap_base, etc, baserights);
65
MAKE_CAPABILITY(etc_cap_all, etc, CAP_MASK_VALID);
66
67
/*
68
* openat(2) with regular file descriptors in non-capability mode
69
* should Just Work (tm).
70
*/
71
CHECK_SYSCALL_SUCCEEDS(openat, etc, "/etc/passwd", O_RDONLY);
72
CHECK_SYSCALL_SUCCEEDS(openat, AT_FDCWD, "/etc/passwd", O_RDONLY);
73
CHECK_SYSCALL_SUCCEEDS(openat, etc, "passwd", O_RDONLY);
74
CHECK_SYSCALL_SUCCEEDS(openat, etc, "../etc/passwd", O_RDONLY);
75
76
/*
77
* Lookups relative to capabilities should be strictly relative.
78
*
79
* When not in capability mode, we don't actually require CAP_LOOKUP.
80
*/
81
CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_ro, "passwd", O_RDONLY);
82
CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_base, "passwd", O_RDONLY);
83
CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "passwd", O_RDONLY);
84
85
CHECK_NOTCAPABLE(openat, etc_cap_ro, "../etc/passwd", O_RDONLY);
86
CHECK_NOTCAPABLE(openat, etc_cap_base, "../etc/passwd", O_RDONLY);
87
88
/*
89
* This requires discussion: do we treat a capability with
90
* CAP_MASK_VALID *exactly* like a non-capability file descriptor
91
* (currently, the implementation says yes)?
92
*/
93
CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "../etc/passwd", O_RDONLY);
94
95
/*
96
* A file opened relative to a capability should itself be a capability.
97
*/
98
CHECK_SYSCALL_SUCCEEDS(cap_getrights, etc_cap_base, &rights);
99
100
REQUIRE(fd = openat(etc_cap_base, "passwd", O_RDONLY));
101
CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights);
102
CHECK_RIGHTS(rights, baserights);
103
104
/*
105
* Enter capability mode; now ALL lookups are strictly relative.
106
*/
107
REQUIRE(cap_enter());
108
109
/*
110
* Relative lookups on regular files or capabilities with CAP_LOOKUP
111
* ought to succeed.
112
*/
113
CHECK_SYSCALL_SUCCEEDS(openat, etc, "passwd", O_RDONLY);
114
CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_ro, "passwd", O_RDONLY);
115
CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_base, "passwd", O_RDONLY);
116
CHECK_SYSCALL_SUCCEEDS(openat, etc_cap_all, "passwd", O_RDONLY);
117
118
/*
119
* Lookup relative to capabilities without CAP_LOOKUP should fail.
120
*/
121
CHECK_NOTCAPABLE(openat, etc_cap, "passwd", O_RDONLY);
122
123
/*
124
* Absolute lookups should fail.
125
*/
126
CHECK_CAPMODE(openat, AT_FDCWD, "/etc/passwd", O_RDONLY);
127
CHECK_NOTCAPABLE(openat, etc, "/etc/passwd", O_RDONLY);
128
129
/*
130
* Lookups containing '..' should fail in capability mode.
131
*/
132
CHECK_NOTCAPABLE(openat, etc, "../etc/passwd", O_RDONLY);
133
CHECK_NOTCAPABLE(openat, etc_cap_ro, "../etc/passwd", O_RDONLY);
134
CHECK_NOTCAPABLE(openat, etc_cap_base, "../etc/passwd", O_RDONLY);
135
136
REQUIRE(fd = openat(etc, "passwd", O_RDONLY));
137
CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights);
138
139
/*
140
* A file opened relative to a capability should itself be a capability.
141
*/
142
REQUIRE(fd = openat(etc_cap_base, "passwd", O_RDONLY));
143
CHECK_SYSCALL_SUCCEEDS(cap_getrights, fd, &rights);
144
CHECK_RIGHTS(rights, baserights);
145
146
return success;
147
}
148
149