View | Details | Raw Unified | Return to bug 222632
Collapse All | Expand All

(-)b/lib/libc/sys/bindat.2 (-11 / +10 lines)
Lines 46-52 Link Here
46
The
46
The
47
.Fn bindat
47
.Fn bindat
48
system call assigns the local protocol address to a socket.
48
system call assigns the local protocol address to a socket.
49
It works just like the
49
When passed the special value
50
.Dv AT_FDCWD
51
in the
52
.Fa fd
53
parameter, the behavior is identical to a call to
54
.Xr bind 2 .
55
Otherwise,
56
.Fn bindat
57
works like the
50
.Xr bind 2
58
.Xr bind 2
51
system call with two exceptions:
59
system call with two exceptions:
52
.Pp
60
.Pp
Lines 60-74 If the file path stored in the Link Here
60
field of the sockaddr_un structure is a relative path, it is located relative
68
field of the sockaddr_un structure is a relative path, it is located relative
61
to the directory associated with the file descriptor
69
to the directory associated with the file descriptor
62
.Fa fd .
70
.Fa fd .
63
If
64
.Fn bindat
65
is passed the special value
66
.Dv AT_FDCWD
67
in the
68
.Fa fd
69
parameter, the current working directory is used and the behavior is identical
70
to a call to
71
.Xr bind 2 .
72
.El
71
.El
73
.Sh RETURN VALUES
72
.Sh RETURN VALUES
74
.Rv -std bindat
73
.Rv -std bindat
Lines 77-83 The Link Here
77
.Fn bindat
76
.Fn bindat
78
system call may fail with the same errors as the
77
system call may fail with the same errors as the
79
.Xr bind 2
78
.Xr bind 2
80
system call for a UNIX domain socket or with the following errors:
79
system call or with the following errors:
81
.Bl -tag -width Er
80
.Bl -tag -width Er
82
.It Bq Er EBADF
81
.It Bq Er EBADF
83
The
82
The
(-)b/lib/libc/sys/connectat.2 (-11 / +10 lines)
Lines 46-52 Link Here
46
The
46
The
47
.Fn connectat
47
.Fn connectat
48
system call initiates a connection on a socket.
48
system call initiates a connection on a socket.
49
It works just like the
49
When passed the special value
50
.Dv AT_FDCWD
51
in the
52
.Fa fd
53
parameter, the behavior is identical to a call to
54
.Xr connect 2 .
55
Otherwise,
56
.Fn connectat
57
works like the
50
.Xr connect 2
58
.Xr connect 2
51
system call with two exceptions:
59
system call with two exceptions:
52
.Pp
60
.Pp
Lines 60-74 If the file path stored in the Link Here
60
field of the sockaddr_un structure is a relative path, it is located relative
68
field of the sockaddr_un structure is a relative path, it is located relative
61
to the directory associated with the file descriptor
69
to the directory associated with the file descriptor
62
.Fa fd .
70
.Fa fd .
63
If
64
.Fn connectat
65
is passed the special value
66
.Dv AT_FDCWD
67
in the
68
.Fa fd
69
parameter, the current working directory is used and the behavior is identical
70
to a call to
71
.Xr connect 2 .
72
.El
71
.El
73
.Sh RETURN VALUES
72
.Sh RETURN VALUES
74
.Rv -std connectat
73
.Rv -std connectat
Lines 77-83 The Link Here
77
.Fn connectat
76
.Fn connectat
78
system call may fail with the same errors as the
77
system call may fail with the same errors as the
79
.Xr connect 2
78
.Xr connect 2
80
system call for a UNIX domain socket or with the following errors:
79
system call or with the following errors:
81
.Bl -tag -width Er
80
.Bl -tag -width Er
82
.It Bq Er EBADF
81
.It Bq Er EBADF
83
The
82
The
(-)b/share/man/man4/rights.4 (-5 / +19 lines)
Lines 94-101 Permit Link Here
94
and
94
and
95
.Xr acl_set_fd_np 3 .
95
.Xr acl_set_fd_np 3 .
96
.It Dv CAP_BIND
96
.It Dv CAP_BIND
97
Permit
97
When not in capabilities mode, permit
98
.Xr bind 2 .
98
.Xr bind 2
99
and
100
.Xr bindat 2
101
with special value
102
.Dv AT_FDCWD
103
in the
104
.Fa fd
105
parameter.
99
Note that sockets can also become bound implicitly as a result of
106
Note that sockets can also become bound implicitly as a result of
100
.Xr connect 2
107
.Xr connect 2
101
or
108
or
Lines 116-124 An alias to Link Here
116
and
123
and
117
.Dv CAP_LOOKUP .
124
.Dv CAP_LOOKUP .
118
.It Dv CAP_CONNECT
125
.It Dv CAP_CONNECT
119
Permit
126
When not in capabilities mode, permit
120
.Xr connect 2 ;
127
.Xr connect 2
121
also required for
128
and
129
.Xr connectat 2
130
with special value
131
.Dv AT_FDCWD
132
in the
133
.Fa fd
134
parameter.
135
This right is also required for
122
.Xr sendto 2
136
.Xr sendto 2
123
with a non-NULL destination address.
137
with a non-NULL destination address.
124
.It Dv CAP_CONNECTAT
138
.It Dv CAP_CONNECTAT
(-)b/sys/kern/uipc_syscalls.c (+10 lines)
Lines 185-190 kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) Link Here
185
	cap_rights_t rights;
185
	cap_rights_t rights;
186
	int error;
186
	int error;
187
187
188
#ifdef CAPABILITY_MODE
189
	if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
190
		return (ECAPMODE);
191
#endif
192
188
	AUDIT_ARG_FD(fd);
193
	AUDIT_ARG_FD(fd);
189
	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
194
	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
190
	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND),
195
	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND),
Lines 481-486 kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) Link Here
481
	cap_rights_t rights;
486
	cap_rights_t rights;
482
	int error, interrupted = 0;
487
	int error, interrupted = 0;
483
488
489
#ifdef CAPABILITY_MODE
490
	if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD))
491
		return (ECAPMODE);
492
#endif
493
484
	AUDIT_ARG_FD(fd);
494
	AUDIT_ARG_FD(fd);
485
	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
495
	AUDIT_ARG_SOCKADDR(td, dirfd, sa);
486
	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT),
496
	error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT),
(-)b/tests/sys/Makefile (+1 lines)
Lines 4-9 TESTSDIR= ${TESTSBASE}/sys Link Here
4
4
5
TESTS_SUBDIRS+=		acl
5
TESTS_SUBDIRS+=		acl
6
TESTS_SUBDIRS+=		aio
6
TESTS_SUBDIRS+=		aio
7
TESTS_SUBDIRS+=		capsicum
7
TESTS_SUBDIRS+=		fifo
8
TESTS_SUBDIRS+=		fifo
8
TESTS_SUBDIRS+=		file
9
TESTS_SUBDIRS+=		file
9
TESTS_SUBDIRS+=		fs
10
TESTS_SUBDIRS+=		fs
(-)b/tests/sys/capsicum/Makefile (+10 lines)
Added Link Here
1
# $FreeBSD$
2
3
PACKAGE=	tests
4
5
TESTSDIR=		${TESTSBASE}/sys/capsicum
6
7
ATF_TESTS_C+=	bindat_connectat
8
CFLAGS.bindat_connectat.c+=	-I${SRCTOP}/tests
9
10
.include <bsd.test.mk>
(-)b/tests/sys/capsicum/bindat_connectat.c (+233 lines)
Added Link Here
1
/*
2
 * Copyright (c) 2017 Jan Kokemüller
3
 *
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions
6
 * are met:
7
 * 1. Redistributions of source code must retain the above copyright
8
 *    notice, this list of conditions and the following disclaimer.
9
 * 2. Redistributions in binary form must reproduce the above copyright
10
 *    notice, this list of conditions and the following disclaimer in the
11
 *    documentation and/or other materials provided with the distribution.
12
 *
13
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23
 * SUCH DAMAGE.
24
 */
25
26
#include <sys/cdefs.h>
27
__FBSDID("$FreeBSD$");
28
29
#include <sys/param.h>
30
#include <sys/capsicum.h>
31
#include <sys/socket.h>
32
#include <sys/sysctl.h>
33
#include <sys/stat.h>
34
35
#include <netinet/in.h>
36
#include <arpa/inet.h>
37
38
#include <atf-c.h>
39
#include <dlfcn.h>
40
#include <errno.h>
41
#include <stdarg.h>
42
#include <stdlib.h>
43
#include <string.h>
44
45
#include "freebsd_test_suite/macros.h"
46
47
static int rootfd = -1;
48
49
/* circumvent bug 215690 */
50
int
51
open(const char *path, int flags, ...)
52
{
53
	mode_t mode = 0;
54
55
	if (flags & O_CREAT) {
56
		va_list ap;
57
		va_start(ap, flags);
58
		mode = (mode_t) va_arg(ap, int);
59
		va_end(ap);
60
	}
61
62
	if (path && path[0] == '/' && rootfd >= 0) {
63
		return (openat(rootfd, path + 1, flags, mode));
64
	} else {
65
		return (openat(AT_FDCWD, path, flags, mode));
66
	}
67
}
68
69
static void
70
check_capsicum(void)
71
{
72
	ATF_REQUIRE_FEATURE("security_capabilities");
73
	ATF_REQUIRE_FEATURE("security_capability_mode");
74
75
	ATF_REQUIRE((rootfd = open("/", O_EXEC | O_CLOEXEC)) >= 0);
76
}
77
78
typedef int (*socket_fun)(int, const struct sockaddr *, socklen_t);
79
80
static int
81
connectat_fdcwd(int s, const struct sockaddr *name, socklen_t namelen)
82
{
83
84
	return (connectat(AT_FDCWD, s, name, namelen));
85
}
86
87
static int
88
bindat_fdcwd(int s, const struct sockaddr *name, socklen_t namelen)
89
{
90
91
	return (bindat(AT_FDCWD, s, name, namelen));
92
}
93
94
95
ATF_TC(bindat_connectat_1);
96
ATF_TC_HEAD(bindat_connectat_1, tc)
97
{
98
	atf_tc_set_md_var(tc, "descr",
99
	    "Verify that connect/bind work in normal case");
100
}
101
102
static void
103
check_1(socket_fun f, int s, const struct sockaddr_in *name)
104
{
105
106
	ATF_REQUIRE((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
107
	ATF_REQUIRE_ERRNO(EAFNOSUPPORT,
108
	    f(s, (const struct sockaddr *)(name),
109
	        sizeof(struct sockaddr_in)) < 0);
110
}
111
112
ATF_TC_BODY(bindat_connectat_1, tc)
113
{
114
	struct sockaddr_in sin;
115
116
	memset(&sin, 0, sizeof(sin));
117
	sin.sin_family = AF_INET;
118
	sin.sin_port = htons(0);
119
	sin.sin_addr.s_addr = htonl(0xE0000000);
120
121
	check_1(bindat_fdcwd, 0, &sin);
122
	check_1(bind, 0, &sin);
123
	check_1(connectat_fdcwd, 0, &sin);
124
	check_1(connect, 0, &sin);
125
}
126
127
128
ATF_TC(bindat_connectat_2);
129
ATF_TC_HEAD(bindat_connectat_2, tc)
130
{
131
	atf_tc_set_md_var(tc, "descr",
132
	    "Verify that connect/bind are disabled in cap-mode");
133
}
134
135
static void
136
check_2(socket_fun f, int s, const struct sockaddr_in *name)
137
{
138
139
	ATF_REQUIRE_ERRNO(ECAPMODE,
140
	    f(s, (const struct sockaddr *)name,
141
	        sizeof(struct sockaddr_in)) < 0);
142
}
143
144
ATF_TC_BODY(bindat_connectat_2, tc)
145
{
146
	int sock;
147
	struct sockaddr_in sin;
148
149
	check_capsicum();
150
151
	ATF_REQUIRE(cap_enter() >= 0);
152
153
	/* note: sock is created _after_ cap_enter() and contains all rights */
154
	ATF_REQUIRE((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
155
156
	memset(&sin, 0, sizeof(sin));
157
	sin.sin_family = AF_INET;
158
	/* dummy port and multicast address (224.0.0.0) to distinguish two
159
	 * cases:
160
	 *  - ECAPMODE/ENOTCAPABLE --> call blocked by capsicum
161
	 *  - EAFNOSUPPORT --> call went through to protocol layer
162
	 */
163
	sin.sin_port = htons(0);
164
	sin.sin_addr.s_addr = htonl(0xE0000000);
165
166
	check_2(bindat_fdcwd, sock, &sin);
167
	check_2(bind, sock, &sin);
168
	check_2(connectat_fdcwd, sock, &sin);
169
	check_2(connect, sock, &sin);
170
}
171
172
173
ATF_TC(bindat_connectat_3);
174
ATF_TC_HEAD(bindat_connectat_3, tc)
175
{
176
	atf_tc_set_md_var(tc, "descr",
177
	    "Check that taking away CAP_BIND/CAP_CONNECT "
178
	    "sabotages bind/connect");
179
}
180
181
static void
182
check_3(socket_fun f, int s, const struct sockaddr_in *name,
183
    cap_rights_t *rights, cap_rights_t *sub_rights)
184
{
185
186
	ATF_REQUIRE((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0);
187
	ATF_REQUIRE(cap_rights_limit(s, rights) >= 0);
188
	ATF_REQUIRE_ERRNO(EAFNOSUPPORT,
189
	    f(s, (const struct sockaddr *)name,
190
	        sizeof(struct sockaddr_in)) < 0);
191
	ATF_REQUIRE(cap_rights_limit(s,
192
	                cap_rights_remove(rights, sub_rights)) >= 0);
193
	ATF_REQUIRE_ERRNO(ENOTCAPABLE,
194
	    f(s, (const struct sockaddr *)name,
195
	        sizeof(struct sockaddr_in)) < 0);
196
}
197
198
ATF_TC_BODY(bindat_connectat_3, tc)
199
{
200
	struct sockaddr_in sin;
201
	cap_rights_t rights, sub_rights;
202
203
	check_capsicum();
204
205
	memset(&sin, 0, sizeof(sin));
206
	sin.sin_family = AF_INET;
207
	sin.sin_port = htons(0);
208
	sin.sin_addr.s_addr = htonl(0xE0000000);
209
210
	check_3(bindat_fdcwd, 0, &sin,
211
	    cap_rights_init(&rights, CAP_SOCK_SERVER),
212
	    cap_rights_init(&sub_rights, CAP_BIND));
213
	check_3(bind, 0, &sin,
214
	    cap_rights_init(&rights, CAP_SOCK_SERVER),
215
	    cap_rights_init(&sub_rights, CAP_BIND));
216
	check_3(connectat_fdcwd, 0, &sin,
217
	    cap_rights_init(&rights, CAP_SOCK_CLIENT),
218
	    cap_rights_init(&sub_rights, CAP_CONNECT));
219
	check_3(connect, 0, &sin,
220
	    cap_rights_init(&rights, CAP_SOCK_CLIENT),
221
	    cap_rights_init(&sub_rights, CAP_CONNECT));
222
}
223
224
225
ATF_TP_ADD_TCS(tp)
226
{
227
228
	ATF_TP_ADD_TC(tp, bindat_connectat_1);
229
	ATF_TP_ADD_TC(tp, bindat_connectat_2);
230
	ATF_TP_ADD_TC(tp, bindat_connectat_3);
231
232
	return (atf_no_error());
233
}

Return to bug 222632