FreeBSD Bugzilla – Attachment 187942 Details for
Bug 222632
connect(2) not available in capability mode
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Disallow connectat/bindat AT_FDCWD in capabilities mode
disallow-connectat-in-capmode.patch (text/plain), 11.09 KB, created by
Jan Kokemüller
on 2017-11-12 15:42:34 UTC
(
hide
)
Description:
Disallow connectat/bindat AT_FDCWD in capabilities mode
Filename:
MIME Type:
Creator:
Jan Kokemüller
Created:
2017-11-12 15:42:34 UTC
Size:
11.09 KB
patch
obsolete
>diff --git a/lib/libc/sys/bindat.2 b/lib/libc/sys/bindat.2 >index 692099092d6c..12c9b3767689 100644 >--- a/lib/libc/sys/bindat.2 >+++ b/lib/libc/sys/bindat.2 >@@ -46,7 +46,15 @@ > The > .Fn bindat > system call assigns the local protocol address to a socket. >-It works just like the >+When passed the special value >+.Dv AT_FDCWD >+in the >+.Fa fd >+parameter, the behavior is identical to a call to >+.Xr bind 2 . >+Otherwise, >+.Fn bindat >+works like the > .Xr bind 2 > system call with two exceptions: > .Pp >@@ -60,15 +68,6 @@ If the file path stored in the > field of the sockaddr_un structure is a relative path, it is located relative > to the directory associated with the file descriptor > .Fa fd . >-If >-.Fn bindat >-is passed the special value >-.Dv AT_FDCWD >-in the >-.Fa fd >-parameter, the current working directory is used and the behavior is identical >-to a call to >-.Xr bind 2 . > .El > .Sh RETURN VALUES > .Rv -std bindat >@@ -77,7 +76,7 @@ The > .Fn bindat > system call may fail with the same errors as the > .Xr bind 2 >-system call for a UNIX domain socket or with the following errors: >+system call or with the following errors: > .Bl -tag -width Er > .It Bq Er EBADF > The >diff --git a/lib/libc/sys/connectat.2 b/lib/libc/sys/connectat.2 >index 759b7eac8e2e..1d7e740b89c4 100644 >--- a/lib/libc/sys/connectat.2 >+++ b/lib/libc/sys/connectat.2 >@@ -46,7 +46,15 @@ > The > .Fn connectat > system call initiates a connection on a socket. >-It works just like the >+When passed the special value >+.Dv AT_FDCWD >+in the >+.Fa fd >+parameter, the behavior is identical to a call to >+.Xr connect 2 . >+Otherwise, >+.Fn connectat >+works like the > .Xr connect 2 > system call with two exceptions: > .Pp >@@ -60,15 +68,6 @@ If the file path stored in the > field of the sockaddr_un structure is a relative path, it is located relative > to the directory associated with the file descriptor > .Fa fd . >-If >-.Fn connectat >-is passed the special value >-.Dv AT_FDCWD >-in the >-.Fa fd >-parameter, the current working directory is used and the behavior is identical >-to a call to >-.Xr connect 2 . > .El > .Sh RETURN VALUES > .Rv -std connectat >@@ -77,7 +76,7 @@ The > .Fn connectat > system call may fail with the same errors as the > .Xr connect 2 >-system call for a UNIX domain socket or with the following errors: >+system call or with the following errors: > .Bl -tag -width Er > .It Bq Er EBADF > The >diff --git a/share/man/man4/rights.4 b/share/man/man4/rights.4 >index da9a5aa8a980..097a84f18f67 100644 >--- a/share/man/man4/rights.4 >+++ b/share/man/man4/rights.4 >@@ -94,8 +94,15 @@ Permit > and > .Xr acl_set_fd_np 3 . > .It Dv CAP_BIND >-Permit >-.Xr bind 2 . >+When not in capabilities mode, permit >+.Xr bind 2 >+and >+.Xr bindat 2 >+with special value >+.Dv AT_FDCWD >+in the >+.Fa fd >+parameter. > Note that sockets can also become bound implicitly as a result of > .Xr connect 2 > or >@@ -116,9 +123,16 @@ An alias to > and > .Dv CAP_LOOKUP . > .It Dv CAP_CONNECT >-Permit >-.Xr connect 2 ; >-also required for >+When not in capabilities mode, permit >+.Xr connect 2 >+and >+.Xr connectat 2 >+with special value >+.Dv AT_FDCWD >+in the >+.Fa fd >+parameter. >+This right is also required for > .Xr sendto 2 > with a non-NULL destination address. > .It Dv CAP_CONNECTAT >diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c >index ca2f157b0041..0ef92f314e78 100644 >--- a/sys/kern/uipc_syscalls.c >+++ b/sys/kern/uipc_syscalls.c >@@ -185,6 +185,11 @@ kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) > cap_rights_t rights; > int error; > >+#ifdef CAPABILITY_MODE >+ if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD)) >+ return (ECAPMODE); >+#endif >+ > AUDIT_ARG_FD(fd); > AUDIT_ARG_SOCKADDR(td, dirfd, sa); > error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND), >@@ -481,6 +486,11 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa) > cap_rights_t rights; > int error, interrupted = 0; > >+#ifdef CAPABILITY_MODE >+ if (IN_CAPABILITY_MODE(td) && (dirfd == AT_FDCWD)) >+ return (ECAPMODE); >+#endif >+ > AUDIT_ARG_FD(fd); > AUDIT_ARG_SOCKADDR(td, dirfd, sa); > error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT), >diff --git a/tests/sys/Makefile b/tests/sys/Makefile >index 9c053d94ac76..b8aaab0b34e1 100644 >--- a/tests/sys/Makefile >+++ b/tests/sys/Makefile >@@ -4,6 +4,7 @@ TESTSDIR= ${TESTSBASE}/sys > > TESTS_SUBDIRS+= acl > TESTS_SUBDIRS+= aio >+TESTS_SUBDIRS+= capsicum > TESTS_SUBDIRS+= fifo > TESTS_SUBDIRS+= file > TESTS_SUBDIRS+= fs >diff --git a/tests/sys/capsicum/Makefile b/tests/sys/capsicum/Makefile >new file mode 100644 >index 000000000000..e1ddcba623bb >--- /dev/null >+++ b/tests/sys/capsicum/Makefile >@@ -0,0 +1,10 @@ >+# $FreeBSD$ >+ >+PACKAGE= tests >+ >+TESTSDIR= ${TESTSBASE}/sys/capsicum >+ >+ATF_TESTS_C+= bindat_connectat >+CFLAGS.bindat_connectat.c+= -I${SRCTOP}/tests >+ >+.include <bsd.test.mk> >diff --git a/tests/sys/capsicum/bindat_connectat.c b/tests/sys/capsicum/bindat_connectat.c >new file mode 100644 >index 000000000000..03695128a675 >--- /dev/null >+++ b/tests/sys/capsicum/bindat_connectat.c >@@ -0,0 +1,233 @@ >+/* >+ * Copyright (c) 2017 Jan Kokemüller >+ * >+ * Redistribution and use in source and binary forms, with or without >+ * modification, are permitted provided that the following conditions >+ * are met: >+ * 1. Redistributions of source code must retain the above copyright >+ * notice, this list of conditions and the following disclaimer. >+ * 2. Redistributions in binary form must reproduce the above copyright >+ * notice, this list of conditions and the following disclaimer in the >+ * documentation and/or other materials provided with the distribution. >+ * >+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND >+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE >+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE >+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE >+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL >+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS >+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) >+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT >+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY >+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF >+ * SUCH DAMAGE. >+ */ >+ >+#include <sys/cdefs.h> >+__FBSDID("$FreeBSD$"); >+ >+#include <sys/param.h> >+#include <sys/capsicum.h> >+#include <sys/socket.h> >+#include <sys/sysctl.h> >+#include <sys/stat.h> >+ >+#include <netinet/in.h> >+#include <arpa/inet.h> >+ >+#include <atf-c.h> >+#include <dlfcn.h> >+#include <errno.h> >+#include <stdarg.h> >+#include <stdlib.h> >+#include <string.h> >+ >+#include "freebsd_test_suite/macros.h" >+ >+static int rootfd = -1; >+ >+/* circumvent bug 215690 */ >+int >+open(const char *path, int flags, ...) >+{ >+ mode_t mode = 0; >+ >+ if (flags & O_CREAT) { >+ va_list ap; >+ va_start(ap, flags); >+ mode = (mode_t) va_arg(ap, int); >+ va_end(ap); >+ } >+ >+ if (path && path[0] == '/' && rootfd >= 0) { >+ return (openat(rootfd, path + 1, flags, mode)); >+ } else { >+ return (openat(AT_FDCWD, path, flags, mode)); >+ } >+} >+ >+static void >+check_capsicum(void) >+{ >+ ATF_REQUIRE_FEATURE("security_capabilities"); >+ ATF_REQUIRE_FEATURE("security_capability_mode"); >+ >+ ATF_REQUIRE((rootfd = open("/", O_EXEC | O_CLOEXEC)) >= 0); >+} >+ >+typedef int (*socket_fun)(int, const struct sockaddr *, socklen_t); >+ >+static int >+connectat_fdcwd(int s, const struct sockaddr *name, socklen_t namelen) >+{ >+ >+ return (connectat(AT_FDCWD, s, name, namelen)); >+} >+ >+static int >+bindat_fdcwd(int s, const struct sockaddr *name, socklen_t namelen) >+{ >+ >+ return (bindat(AT_FDCWD, s, name, namelen)); >+} >+ >+ >+ATF_TC(bindat_connectat_1); >+ATF_TC_HEAD(bindat_connectat_1, tc) >+{ >+ atf_tc_set_md_var(tc, "descr", >+ "Verify that connect/bind work in normal case"); >+} >+ >+static void >+check_1(socket_fun f, int s, const struct sockaddr_in *name) >+{ >+ >+ ATF_REQUIRE((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0); >+ ATF_REQUIRE_ERRNO(EAFNOSUPPORT, >+ f(s, (const struct sockaddr *)(name), >+ sizeof(struct sockaddr_in)) < 0); >+} >+ >+ATF_TC_BODY(bindat_connectat_1, tc) >+{ >+ struct sockaddr_in sin; >+ >+ memset(&sin, 0, sizeof(sin)); >+ sin.sin_family = AF_INET; >+ sin.sin_port = htons(0); >+ sin.sin_addr.s_addr = htonl(0xE0000000); >+ >+ check_1(bindat_fdcwd, 0, &sin); >+ check_1(bind, 0, &sin); >+ check_1(connectat_fdcwd, 0, &sin); >+ check_1(connect, 0, &sin); >+} >+ >+ >+ATF_TC(bindat_connectat_2); >+ATF_TC_HEAD(bindat_connectat_2, tc) >+{ >+ atf_tc_set_md_var(tc, "descr", >+ "Verify that connect/bind are disabled in cap-mode"); >+} >+ >+static void >+check_2(socket_fun f, int s, const struct sockaddr_in *name) >+{ >+ >+ ATF_REQUIRE_ERRNO(ECAPMODE, >+ f(s, (const struct sockaddr *)name, >+ sizeof(struct sockaddr_in)) < 0); >+} >+ >+ATF_TC_BODY(bindat_connectat_2, tc) >+{ >+ int sock; >+ struct sockaddr_in sin; >+ >+ check_capsicum(); >+ >+ ATF_REQUIRE(cap_enter() >= 0); >+ >+ /* note: sock is created _after_ cap_enter() and contains all rights */ >+ ATF_REQUIRE((sock = socket(AF_INET, SOCK_STREAM, 0)) >= 0); >+ >+ memset(&sin, 0, sizeof(sin)); >+ sin.sin_family = AF_INET; >+ /* dummy port and multicast address (224.0.0.0) to distinguish two >+ * cases: >+ * - ECAPMODE/ENOTCAPABLE --> call blocked by capsicum >+ * - EAFNOSUPPORT --> call went through to protocol layer >+ */ >+ sin.sin_port = htons(0); >+ sin.sin_addr.s_addr = htonl(0xE0000000); >+ >+ check_2(bindat_fdcwd, sock, &sin); >+ check_2(bind, sock, &sin); >+ check_2(connectat_fdcwd, sock, &sin); >+ check_2(connect, sock, &sin); >+} >+ >+ >+ATF_TC(bindat_connectat_3); >+ATF_TC_HEAD(bindat_connectat_3, tc) >+{ >+ atf_tc_set_md_var(tc, "descr", >+ "Check that taking away CAP_BIND/CAP_CONNECT " >+ "sabotages bind/connect"); >+} >+ >+static void >+check_3(socket_fun f, int s, const struct sockaddr_in *name, >+ cap_rights_t *rights, cap_rights_t *sub_rights) >+{ >+ >+ ATF_REQUIRE((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0); >+ ATF_REQUIRE(cap_rights_limit(s, rights) >= 0); >+ ATF_REQUIRE_ERRNO(EAFNOSUPPORT, >+ f(s, (const struct sockaddr *)name, >+ sizeof(struct sockaddr_in)) < 0); >+ ATF_REQUIRE(cap_rights_limit(s, >+ cap_rights_remove(rights, sub_rights)) >= 0); >+ ATF_REQUIRE_ERRNO(ENOTCAPABLE, >+ f(s, (const struct sockaddr *)name, >+ sizeof(struct sockaddr_in)) < 0); >+} >+ >+ATF_TC_BODY(bindat_connectat_3, tc) >+{ >+ struct sockaddr_in sin; >+ cap_rights_t rights, sub_rights; >+ >+ check_capsicum(); >+ >+ memset(&sin, 0, sizeof(sin)); >+ sin.sin_family = AF_INET; >+ sin.sin_port = htons(0); >+ sin.sin_addr.s_addr = htonl(0xE0000000); >+ >+ check_3(bindat_fdcwd, 0, &sin, >+ cap_rights_init(&rights, CAP_SOCK_SERVER), >+ cap_rights_init(&sub_rights, CAP_BIND)); >+ check_3(bind, 0, &sin, >+ cap_rights_init(&rights, CAP_SOCK_SERVER), >+ cap_rights_init(&sub_rights, CAP_BIND)); >+ check_3(connectat_fdcwd, 0, &sin, >+ cap_rights_init(&rights, CAP_SOCK_CLIENT), >+ cap_rights_init(&sub_rights, CAP_CONNECT)); >+ check_3(connect, 0, &sin, >+ cap_rights_init(&rights, CAP_SOCK_CLIENT), >+ cap_rights_init(&sub_rights, CAP_CONNECT)); >+} >+ >+ >+ATF_TP_ADD_TCS(tp) >+{ >+ >+ ATF_TP_ADD_TC(tp, bindat_connectat_1); >+ ATF_TP_ADD_TC(tp, bindat_connectat_2); >+ ATF_TP_ADD_TC(tp, bindat_connectat_3); >+ >+ return (atf_no_error()); >+}
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 222632
: 187942