summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/tcpdump/tcpdump.c37
-rw-r--r--lib/libc/Makefile1
-rw-r--r--lib/libc/capability/Makefile.inc19
-rw-r--r--lib/libc/capability/Symbol.map14
-rw-r--r--lib/libc/include/compat.h2
-rw-r--r--lib/libc/sys/Symbol.map3
-rw-r--r--lib/libprocstat/libprocstat.c6
-rw-r--r--lib/libprocstat/libprocstat.h1
-rw-r--r--sbin/dhclient/bpf.c12
-rw-r--r--sbin/dhclient/dhclient.c31
-rw-r--r--sbin/hastd/subr.c9
-rw-r--r--sys/amd64/linux32/linux32_machdep.c5
-rw-r--r--sys/bsm/audit_kevents.h1
-rw-r--r--sys/bsm/audit_record.h4
-rw-r--r--sys/cddl/compat/opensolaris/sys/file.h4
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c15
-rw-r--r--sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c3
-rw-r--r--sys/compat/freebsd32/freebsd32_capability.c20
-rw-r--r--sys/compat/freebsd32/freebsd32_ioctl.c4
-rw-r--r--sys/compat/freebsd32/freebsd32_misc.c5
-rw-r--r--sys/compat/freebsd32/syscalls.master16
-rw-r--r--sys/compat/linux/linux_file.c17
-rw-r--r--sys/compat/linux/linux_ioctl.c82
-rw-r--r--sys/compat/linux/linux_socket.c4
-rw-r--r--sys/compat/svr4/svr4_fcntl.c16
-rw-r--r--sys/compat/svr4/svr4_filio.c3
-rw-r--r--sys/compat/svr4/svr4_ioctl.c4
-rw-r--r--sys/compat/svr4/svr4_misc.c10
-rw-r--r--sys/compat/svr4/svr4_stream.c12
-rw-r--r--sys/conf/files1
-rw-r--r--sys/dev/aac/aac_linux.c4
-rw-r--r--sys/dev/amr/amr_linux.c4
-rw-r--r--sys/dev/filemon/filemon.c16
-rw-r--r--sys/dev/hwpmc/hwpmc_logging.c4
-rw-r--r--sys/dev/ipmi/ipmi_linux.c4
-rw-r--r--sys/dev/iscsi_initiator/iscsi.c7
-rw-r--r--sys/dev/mfi/mfi_linux.c4
-rw-r--r--sys/dev/tdfx/tdfx_linux.c4
-rw-r--r--sys/fs/fdescfs/fdesc_vnops.c4
-rw-r--r--sys/fs/fuse/fuse_vfsops.c3
-rw-r--r--sys/fs/nfsclient/nfs_clport.c9
-rw-r--r--sys/fs/nfsserver/nfs_nfsdport.c5
-rw-r--r--sys/i386/ibcs2/ibcs2_fcntl.c4
-rw-r--r--sys/i386/ibcs2/ibcs2_ioctl.c4
-rw-r--r--sys/i386/ibcs2/ibcs2_misc.c11
-rw-r--r--sys/i386/linux/linux_machdep.c5
-rw-r--r--sys/kern/capabilities.conf3
-rw-r--r--sys/kern/kern_descrip.c137
-rw-r--r--sys/kern/kern_event.c12
-rw-r--r--sys/kern/kern_exec.c4
-rw-r--r--sys/kern/kern_ktrace.c8
-rw-r--r--sys/kern/kern_sig.c4
-rw-r--r--sys/kern/subr_capability.c285
-rw-r--r--sys/kern/sys_capability.c170
-rw-r--r--sys/kern/sys_generic.c32
-rw-r--r--sys/kern/sys_procdesc.c12
-rw-r--r--sys/kern/syscalls.master8
-rw-r--r--sys/kern/tty.c4
-rw-r--r--sys/kern/uipc_mqueue.c25
-rw-r--r--sys/kern/uipc_sem.c18
-rw-r--r--sys/kern/uipc_syscalls.c82
-rw-r--r--sys/kern/uipc_usrreq.c8
-rw-r--r--sys/kern/vfs_acl.c18
-rw-r--r--sys/kern/vfs_aio.c11
-rw-r--r--sys/kern/vfs_extattr.c17
-rw-r--r--sys/kern/vfs_lookup.c33
-rw-r--r--sys/kern/vfs_syscalls.c140
-rw-r--r--sys/netsmb/smb_dev.c3
-rw-r--r--sys/nfsserver/nfs_srvkrpc.c4
-rw-r--r--sys/security/audit/audit.h2
-rw-r--r--sys/security/audit/audit_arg.c4
-rw-r--r--sys/security/audit/audit_bsm.c3
-rw-r--r--sys/security/audit/audit_private.h1
-rw-r--r--sys/security/audit/bsm_token.c16
-rw-r--r--sys/security/mac/mac_syscalls.c6
-rw-r--r--sys/sys/_types.h1
-rw-r--r--sys/sys/capability.h247
-rw-r--r--sys/sys/caprights.h61
-rw-r--r--sys/sys/file.h21
-rw-r--r--sys/sys/filedesc.h9
-rw-r--r--sys/sys/ktrace.h7
-rw-r--r--sys/sys/namei.h29
-rw-r--r--sys/sys/procdesc.h4
-rw-r--r--sys/sys/types.h9
-rw-r--r--sys/sys/user.h4
-rw-r--r--sys/ufs/ffs/ffs_alloc.c7
-rw-r--r--sys/vm/vm_mmap.c12
-rw-r--r--usr.bin/kdump/kdump.c71
-rw-r--r--usr.bin/kdump/mksubr24
-rw-r--r--usr.bin/procstat/procstat_files.c18
-rw-r--r--usr.bin/rwho/rwho.c7
-rw-r--r--usr.bin/uniq/uniq.c13
-rw-r--r--usr.sbin/rwhod/rwhod.c10
93 files changed, 1402 insertions, 675 deletions
diff --git a/contrib/tcpdump/tcpdump.c b/contrib/tcpdump/tcpdump.c
index 48b774d..afcc152 100644
--- a/contrib/tcpdump/tcpdump.c
+++ b/contrib/tcpdump/tcpdump.c
@@ -715,8 +715,9 @@ main(int argc, char **argv)
int status;
FILE *VFile;
#ifdef __FreeBSD__
+ cap_rights_t rights;
int cansandbox;
-#endif
+#endif /* __FreeBSD__ */
#ifdef WIN32
if(wsockinit() != 0) return 1;
@@ -1206,7 +1207,8 @@ main(int argc, char **argv)
if (pd == NULL)
error("%s", ebuf);
#ifdef __FreeBSD__
- if (cap_rights_limit(fileno(pcap_file(pd)), CAP_READ) < 0 &&
+ cap_rights_init(&rights, CAP_READ);
+ if (cap_rights_limit(fileno(pcap_file(pd)), &rights) < 0 &&
errno != ENOSYS) {
error("unable to limit pcap descriptor");
}
@@ -1484,8 +1486,9 @@ main(int argc, char **argv)
if (RFileName == NULL && VFileName == NULL) {
static const unsigned long cmds[] = { BIOCGSTATS };
- if (cap_rights_limit(pcap_fileno(pd),
- CAP_IOCTL | CAP_READ) < 0 && errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_IOCTL, CAP_READ);
+ if (cap_rights_limit(pcap_fileno(pd), &rights) < 0 &&
+ errno != ENOSYS) {
error("unable to limit pcap descriptor");
}
if (cap_ioctls_limit(pcap_fileno(pd), cmds,
@@ -1516,8 +1519,9 @@ main(int argc, char **argv)
if (p == NULL)
error("%s", pcap_geterr(pd));
#ifdef __FreeBSD__
- if (cap_rights_limit(fileno(pcap_dump_file(p)),
- CAP_SEEK | CAP_WRITE) < 0 && errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_SEEK, CAP_WRITE);
+ if (cap_rights_limit(fileno(pcap_dump_file(p)), &rights) < 0 &&
+ errno != ENOSYS) {
error("unable to limit dump descriptor");
}
#endif
@@ -1530,9 +1534,10 @@ main(int argc, char **argv)
error("unable to open directory %s",
dirname(WFileName));
}
- if (cap_rights_limit(dumpinfo.dirfd, CAP_CREATE |
- CAP_FCNTL | CAP_FTRUNCATE | CAP_LOOKUP | CAP_SEEK |
- CAP_WRITE) < 0 && errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_CREATE, CAP_FCNTL,
+ CAP_FTRUNCATE, CAP_LOOKUP, CAP_SEEK, CAP_WRITE);
+ if (cap_rights_limit(dumpinfo.dirfd, &rights) < 0 &&
+ errno != ENOSYS) {
error("unable to limit directory rights");
}
#else /* !__FreeBSD__ */
@@ -1615,7 +1620,7 @@ main(int argc, char **argv)
error("unable to enter the capability mode");
if (cap_sandboxed())
fprintf(stderr, "capability mode sandbox enabled\n");
-#endif
+#endif /* __FreeBSD__ */
do {
status = pcap_loop(pd, cnt, callback, pcap_userdata);
@@ -1657,8 +1662,9 @@ main(int argc, char **argv)
if (pd == NULL)
error("%s", ebuf);
#ifdef __FreeBSD__
+ cap_rights_init(&rights, CAP_READ);
if (cap_rights_limit(fileno(pcap_file(pd)),
- CAP_READ) < 0 && errno != ENOSYS) {
+ &rights) < 0 && errno != ENOSYS) {
error("unable to limit pcap descriptor");
}
#endif
@@ -1830,6 +1836,9 @@ static void
dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
{
struct dump_info *dump_info;
+#ifdef __FreeBSD__
+ cap_rights_t rights;
+#endif
++packets_captured;
@@ -1933,8 +1942,9 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
if (dump_info->p == NULL)
error("%s", pcap_geterr(pd));
#ifdef __FreeBSD__
+ cap_rights_init(&rights, CAP_SEEK, CAP_WRITE);
if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)),
- CAP_SEEK | CAP_WRITE) < 0 && errno != ENOSYS) {
+ &rights) < 0 && errno != ENOSYS) {
error("unable to limit dump descriptor");
}
#endif
@@ -1993,8 +2003,9 @@ dump_packet_and_trunc(u_char *user, const struct pcap_pkthdr *h, const u_char *s
if (dump_info->p == NULL)
error("%s", pcap_geterr(pd));
#ifdef __FreeBSD__
+ cap_rights_init(&rights, CAP_SEEK, CAP_WRITE);
if (cap_rights_limit(fileno(pcap_dump_file(dump_info->p)),
- CAP_SEEK | CAP_WRITE) < 0 && errno != ENOSYS) {
+ &rights) < 0 && errno != ENOSYS) {
error("unable to limit dump descriptor");
}
#endif
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
index cf2d2aa..2806cc7 100644
--- a/lib/libc/Makefile
+++ b/lib/libc/Makefile
@@ -100,6 +100,7 @@ NOASM=
CFLAGS+= -DYP
.include "${.CURDIR}/yp/Makefile.inc"
.endif
+.include "${.CURDIR}/capability/Makefile.inc"
.if ${MK_HESIOD} != "no"
CFLAGS+= -DHESIOD
.endif
diff --git a/lib/libc/capability/Makefile.inc b/lib/libc/capability/Makefile.inc
new file mode 100644
index 0000000..934fc8b
--- /dev/null
+++ b/lib/libc/capability/Makefile.inc
@@ -0,0 +1,19 @@
+# $FreeBSD$
+
+# capability sources
+.PATH: ${.CURDIR}/../../sys/kern
+
+SRCS+= subr_capability.c
+
+SYM_MAPS+= ${.CURDIR}/capability/Symbol.map
+
+#MAN+= cap_rights_init.3
+
+#MLINKS+=cap_rights_init.3 cap_rights_set.3
+#MLINKS+=cap_rights_init.3 cap_rights_clear.3
+#MLINKS+=cap_rights_init.3 cap_rights_is_set.3
+#MLINKS+=cap_rights_init.3 cap_rights_is_valid.3
+#MLINKS+=cap_rights_init.3 cap_rights_merge.3
+#MLINKS+=cap_rights_init.3 cap_rights_remove.3
+#MLINKS+=cap_rights_init.3 cap_rights_contains.3
+
diff --git a/lib/libc/capability/Symbol.map b/lib/libc/capability/Symbol.map
new file mode 100644
index 0000000..c5c18c2
--- /dev/null
+++ b/lib/libc/capability/Symbol.map
@@ -0,0 +1,14 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.3 {
+ __cap_rights_clear;
+ cap_rights_contains;
+ __cap_rights_init;
+ __cap_rights_is_set;
+ cap_rights_is_valid;
+ cap_rights_merge;
+ cap_rights_remove;
+ __cap_rights_set;
+};
diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h
index 3739fe1..7694540 100644
--- a/lib/libc/include/compat.h
+++ b/lib/libc/include/compat.h
@@ -42,8 +42,6 @@ __sym_compat(__semctl, freebsd7___semctl, FBSD_1.0);
__sym_compat(msgctl, freebsd7_msgctl, FBSD_1.0);
__sym_compat(shmctl, freebsd7_shmctl, FBSD_1.0);
-__sym_compat(cap_getrights, cap_rights_get, FBSD_1.2);
-
#undef __sym_compat
#endif /* __LIBC_COMPAT_H__ */
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 4f1104e..222f5f0 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -363,7 +363,6 @@ FBSD_1.1 {
FBSD_1.2 {
cap_enter;
cap_getmode;
- cap_new;
getloginclass;
pdfork;
pdgetpid;
@@ -385,7 +384,7 @@ FBSD_1.3 {
cap_fcntls_limit;
cap_ioctls_get;
cap_ioctls_limit;
- cap_rights_get;
+ __cap_rights_get;
cap_rights_limit;
cap_sandboxed;
chflagsat;
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index dfb5ed3..9056151 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -378,7 +378,7 @@ procstat_freefiles(struct procstat *procstat, struct filestat_list *head)
static struct filestat *
filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags,
- int refcount, off_t offset, char *path, cap_rights_t cap_rights)
+ int refcount, off_t offset, char *path, cap_rights_t *cap_rightsp)
{
struct filestat *entry;
@@ -395,7 +395,7 @@ filestat_new_entry(void *typedep, int type, int fd, int fflags, int uflags,
entry->fs_ref_count = refcount;
entry->fs_offset = offset;
entry->fs_path = path;
- entry->fs_cap_rights = cap_rights;
+ entry->fs_cap_rights = *cap_rightsp;
return (entry);
}
@@ -851,7 +851,7 @@ procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp,
* Create filestat entry.
*/
entry = filestat_new_entry(kif, type, fd, fflags, uflags,
- refcount, offset, path, cap_rights);
+ refcount, offset, path, &cap_rights);
if (entry != NULL)
STAILQ_INSERT_TAIL(head, entry, next);
}
diff --git a/lib/libprocstat/libprocstat.h b/lib/libprocstat/libprocstat.h
index 65a5eb9..7af6ccb 100644
--- a/lib/libprocstat/libprocstat.h
+++ b/lib/libprocstat/libprocstat.h
@@ -36,6 +36,7 @@
#ifndef ZFS
#include <sys/elf.h>
#endif
+#include <sys/caprights.h>
/*
* Vnode types.
diff --git a/sbin/dhclient/bpf.c b/sbin/dhclient/bpf.c
index f435028..c0a1720 100644
--- a/sbin/dhclient/bpf.c
+++ b/sbin/dhclient/bpf.c
@@ -43,6 +43,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/capability.h>
+
#include "dhcpd.h"
#include "privsep.h"
#include <sys/capability.h>
@@ -132,6 +134,7 @@ int dhcp_bpf_wfilter_len = sizeof(dhcp_bpf_wfilter) / sizeof(struct bpf_insn);
void
if_register_send(struct interface_info *info)
{
+ cap_rights_t rights;
struct bpf_version v;
struct bpf_program p;
int sock, on = 1;
@@ -160,7 +163,8 @@ if_register_send(struct interface_info *info)
if (ioctl(info->wfdesc, BIOCLOCK, NULL) < 0)
error("Cannot lock bpf");
- if (cap_rights_limit(info->wfdesc, CAP_WRITE) < 0 && errno != ENOSYS)
+ cap_rights_init(&rights, CAP_WRITE);
+ if (cap_rights_limit(info->wfdesc, &rights) < 0 && errno != ENOSYS)
error("Can't limit bpf descriptor: %m");
/*
@@ -213,6 +217,7 @@ void
if_register_receive(struct interface_info *info)
{
static const unsigned long cmds[2] = { SIOCGIFFLAGS, SIOCGIFMEDIA };
+ cap_rights_t rights;
struct bpf_version v;
struct bpf_program p;
int flag = 1, sz;
@@ -264,10 +269,9 @@ if_register_receive(struct interface_info *info)
if (ioctl(info->rfdesc, BIOCLOCK, NULL) < 0)
error("Cannot lock bpf");
- if (cap_rights_limit(info->rfdesc,
- CAP_IOCTL | CAP_POLL_EVENT | CAP_READ) < 0 && errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_IOCTL, CAP_POLL_EVENT, CAP_READ);
+ if (cap_rights_limit(info->rfdesc, &rights) < 0 && errno != ENOSYS)
error("Can't limit bpf descriptor: %m");
- }
if (cap_ioctls_limit(info->rfdesc, cmds, 2) < 0 && errno != ENOSYS)
error("Can't limit ioctls for bpf descriptor: %m");
}
diff --git a/sbin/dhclient/dhclient.c b/sbin/dhclient/dhclient.c
index c8f05b5..e16e464 100644
--- a/sbin/dhclient/dhclient.c
+++ b/sbin/dhclient/dhclient.c
@@ -56,6 +56,8 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/capability.h>
+
#include "dhcpd.h"
#include "privsep.h"
@@ -346,6 +348,7 @@ main(int argc, char *argv[])
int immediate_daemon = 0;
struct passwd *pw;
pid_t otherpid;
+ cap_rights_t rights;
/* Initially, log errors to stderr as well as to syslogd. */
openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
@@ -477,10 +480,9 @@ main(int argc, char *argv[])
close(pipe_fd[0]);
privfd = pipe_fd[1];
- if (cap_rights_limit(privfd, CAP_READ | CAP_WRITE) < 0 &&
- errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_READ, CAP_WRITE);
+ if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
error("can't limit private descriptor: %m");
- }
if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
error("can't open and lock %s: %m", path_dhclient_db);
@@ -492,10 +494,9 @@ main(int argc, char *argv[])
add_protocol("AF_ROUTE", routefd, routehandler, ifi);
if (shutdown(routefd, SHUT_WR) < 0)
error("can't shutdown route socket: %m");
- if (cap_rights_limit(routefd, CAP_POLL_EVENT | CAP_READ) < 0 &&
- errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_POLL_EVENT, CAP_READ);
+ if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
error("can't limit route socket: %m");
- }
if (chroot(_PATH_VAREMPTY) == -1)
error("chroot");
@@ -1840,13 +1841,15 @@ void
rewrite_client_leases(void)
{
struct client_lease *lp;
+ cap_rights_t rights;
if (!leaseFile) {
leaseFile = fopen(path_dhclient_db, "w");
if (!leaseFile)
error("can't create %s: %m", path_dhclient_db);
- if (cap_rights_limit(fileno(leaseFile), CAP_FSTAT | CAP_FSYNC |
- CAP_FTRUNCATE | CAP_SEEK | CAP_WRITE) < 0 &&
+ cap_rights_init(&rights, CAP_FSTAT, CAP_FSYNC, CAP_FTRUNCATE,
+ CAP_SEEK, CAP_WRITE);
+ if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
errno != ENOSYS) {
error("can't limit lease descriptor: %m");
}
@@ -2354,6 +2357,7 @@ void
go_daemon(void)
{
static int state = 0;
+ cap_rights_t rights;
if (no_daemon || state)
return;
@@ -2366,9 +2370,11 @@ go_daemon(void)
if (daemon(1, 0) == -1)
error("daemon");
+ cap_rights_init(&rights);
+
if (pidfile != NULL) {
pidfile_write(pidfile);
- if (cap_rights_limit(pidfile_fileno(pidfile), CAP_NONE) < 0 &&
+ if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
errno != ENOSYS) {
error("can't limit pidfile descriptor: %m");
}
@@ -2383,11 +2389,12 @@ go_daemon(void)
nullfd = -1;
}
- if (cap_rights_limit(STDIN_FILENO, CAP_NONE) < 0 && errno != ENOSYS)
+ if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
error("can't limit stdin: %m");
- if (cap_rights_limit(STDOUT_FILENO, CAP_WRITE) < 0 && errno != ENOSYS)
+ cap_rights_init(&rights, CAP_WRITE);
+ if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
error("can't limit stdout: %m");
- if (cap_rights_limit(STDERR_FILENO, CAP_WRITE) < 0 && errno != ENOSYS)
+ if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
error("can't limit stderr: %m");
}
diff --git a/sbin/hastd/subr.c b/sbin/hastd/subr.c
index 440061e..0e9930b 100644
--- a/sbin/hastd/subr.c
+++ b/sbin/hastd/subr.c
@@ -231,6 +231,7 @@ drop_privs(const struct hast_resource *res)
pjdlog_common(LOG_DEBUG, 1, errno,
"Unable to sandbox using capsicum");
} else if (res != NULL) {
+ cap_rights_t rights;
static const unsigned long geomcmds[] = {
DIOCGDELETE,
DIOCGFLUSH
@@ -239,8 +240,9 @@ drop_privs(const struct hast_resource *res)
PJDLOG_ASSERT(res->hr_role == HAST_ROLE_PRIMARY ||
res->hr_role == HAST_ROLE_SECONDARY);
- if (cap_rights_limit(res->hr_localfd,
- CAP_FLOCK | CAP_IOCTL | CAP_PREAD | CAP_PWRITE) == -1) {
+ cap_rights_init(&rights, CAP_FLOCK, CAP_IOCTL, CAP_PREAD,
+ CAP_PWRITE);
+ if (cap_rights_limit(res->hr_localfd, &rights) == -1) {
pjdlog_errno(LOG_ERR,
"Unable to limit capability rights on local descriptor");
}
@@ -258,7 +260,8 @@ drop_privs(const struct hast_resource *res)
G_GATE_CMD_DESTROY
};
- if (cap_rights_limit(res->hr_ggatefd, CAP_IOCTL) == -1) {
+ cap_rights_init(&rights, CAP_IOCTL);
+ if (cap_rights_limit(res->hr_ggatefd, &rights) == -1) {
pjdlog_errno(LOG_ERR,
"Unable to limit capability rights to CAP_IOCTL on ggate descriptor");
}
diff --git a/sys/amd64/linux32/linux32_machdep.c b/sys/amd64/linux32/linux32_machdep.c
index 65f034a..3dd8f7a 100644
--- a/sys/amd64/linux32/linux32_machdep.c
+++ b/sys/amd64/linux32/linux32_machdep.c
@@ -519,6 +519,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
} */ bsd_args;
int error;
struct file *fp;
+ cap_rights_t rights;
error = 0;
bsd_args.flags = 0;
@@ -567,7 +568,9 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
* protection options specified.
*/
- if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0)
+ error = fget(td, bsd_args.fd,
+ cap_rights_init(&rights, CAP_MMAP), &fp);
+ if (error != 0)
return (error);
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
diff --git a/sys/bsm/audit_kevents.h b/sys/bsm/audit_kevents.h
index da2bc7c..303d37f 100644
--- a/sys/bsm/audit_kevents.h
+++ b/sys/bsm/audit_kevents.h
@@ -589,6 +589,7 @@
#define AUE_POSIX_OPENPT 43185 /* FreeBSD. */
#define AUE_CAP_NEW 43186 /* TrustedBSD. */
#define AUE_CAP_RIGHTS_GET 43187 /* TrustedBSD. */
+#define AUE_CAP_GETRIGHTS AUE_CAP_RIGHTS_GET
#define AUE_CAP_ENTER 43188 /* TrustedBSD. */
#define AUE_CAP_GETMODE 43189 /* TrustedBSD. */
#define AUE_POSIX_SPAWN 43190 /* Darwin. */
diff --git a/sys/bsm/audit_record.h b/sys/bsm/audit_record.h
index 706c6f3..7e6074f 100644
--- a/sys/bsm/audit_record.h
+++ b/sys/bsm/audit_record.h
@@ -34,6 +34,7 @@
#define _BSM_AUDIT_RECORD_H_
#include <sys/time.h> /* struct timeval */
+#include <sys/caprights.h> /* cap_rights_t */
/*
* Token type identifiers.
@@ -126,6 +127,8 @@
#define AUT_SOCKINET128 0x81 /* XXX */
#define AUT_SOCKUNIX 0x82 /* XXX */
+#define AUT_RIGHTS 0x83
+
/* print values for the arbitrary token */
#define AUP_BINARY 0
#define AUP_OCTAL 1
@@ -248,6 +251,7 @@ token_t *au_to_process32_ex(au_id_t auid, uid_t euid, gid_t egid,
au_tid_addr_t *tid);
token_t *au_to_process64_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
gid_t rgid, pid_t pid, au_asid_t sid, au_tid_addr_t *tid);
+token_t *au_to_rights(cap_rights_t *rightsp);
token_t *au_to_return(char status, uint32_t ret);
token_t *au_to_return32(char status, uint32_t ret);
token_t *au_to_return64(char status, uint64_t ret);
diff --git a/sys/cddl/compat/opensolaris/sys/file.h b/sys/cddl/compat/opensolaris/sys/file.h
index 0b8f875..a1c1d45 100644
--- a/sys/cddl/compat/opensolaris/sys/file.h
+++ b/sys/cddl/compat/opensolaris/sys/file.h
@@ -39,11 +39,11 @@ typedef struct file file_t;
#include <sys/capability.h>
static __inline file_t *
-getf(int fd, cap_rights_t rights)
+getf(int fd, cap_rights_t *rightsp)
{
struct file *fp;
- if (fget(curthread, fd, rights, &fp) == 0)
+ if (fget(curthread, fd, rightsp, &fp) == 0)
return (fp);
return (NULL);
}
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
index 10456f8..e9fba26 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c
@@ -4005,6 +4005,7 @@ zfs_ioc_recv(zfs_cmd_t *zc)
char *origin = NULL;
char *tosnap;
char tofs[ZFS_MAXNAMELEN];
+ cap_rights_t rights;
boolean_t first_recvd_props = B_FALSE;
if (dataset_namecheck(zc->zc_value, NULL, NULL) != 0 ||
@@ -4022,7 +4023,7 @@ zfs_ioc_recv(zfs_cmd_t *zc)
return (error);
fd = zc->zc_cookie;
- fp = getf(fd, CAP_PREAD);
+ fp = getf(fd, cap_rights_init(&rights, CAP_PREAD));
if (fp == NULL) {
nvlist_free(props);
return (SET_ERROR(EBADF));
@@ -4260,7 +4261,11 @@ zfs_ioc_send(zfs_cmd_t *zc)
dsl_dataset_rele(tosnap, FTAG);
dsl_pool_rele(dp, FTAG);
} else {
- file_t *fp = getf(zc->zc_cookie, CAP_WRITE);
+ file_t *fp;
+ cap_rights_t rights;
+
+ fp = getf(zc->zc_cookie,
+ cap_rights_init(&rights, CAP_WRITE));
if (fp == NULL)
return (SET_ERROR(EBADF));
@@ -4851,10 +4856,11 @@ static int
zfs_ioc_diff(zfs_cmd_t *zc)
{
file_t *fp;
+ cap_rights_t rights;
offset_t off;
int error;
- fp = getf(zc->zc_cookie, CAP_WRITE);
+ fp = getf(zc->zc_cookie, cap_rights_init(&rights, CAP_WRITE));
if (fp == NULL)
return (SET_ERROR(EBADF));
@@ -5214,6 +5220,7 @@ zfs_ioc_unjail(zfs_cmd_t *zc)
static int
zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
{
+ cap_rights_t rights;
int error;
offset_t off;
char *fromname = NULL;
@@ -5225,7 +5232,7 @@ zfs_ioc_send_new(const char *snapname, nvlist_t *innvl, nvlist_t *outnvl)
(void) nvlist_lookup_string(innvl, "fromsnap", &fromname);
- file_t *fp = getf(fd, CAP_READ);
+ file_t *fp = getf(fd, cap_rights_init(&rights, CAP_READ));
if (fp == NULL)
return (SET_ERROR(EBADF));
diff --git a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c
index 05252cb..6a90b9c 100644
--- a/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c
+++ b/sys/cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c
@@ -122,10 +122,11 @@ zfs_onexit_fd_hold(int fd, minor_t *minorp)
{
file_t *fp, *tmpfp;
zfs_onexit_t *zo;
+ cap_rights_t rights;
void *data;
int error;
- fp = getf(fd, CAP_NONE);
+ fp = getf(fd, cap_rights_init(&rights));
if (fp == NULL)
return (SET_ERROR(EBADF));
diff --git a/sys/compat/freebsd32/freebsd32_capability.c b/sys/compat/freebsd32/freebsd32_capability.c
index e17c394..b23cf95 100644
--- a/sys/compat/freebsd32/freebsd32_capability.c
+++ b/sys/compat/freebsd32/freebsd32_capability.c
@@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$");
#include <security/audit/audit.h>
-#include <compat/freebsd32/freebsd32_misc.h>
#include <compat/freebsd32/freebsd32_proto.h>
#ifdef CAPABILITIES
@@ -50,17 +49,6 @@ __FBSDID("$FreeBSD$");
MALLOC_DECLARE(M_FILECAPS);
int
-freebsd32_cap_rights_limit(struct thread *td,
- struct freebsd32_cap_rights_limit_args *uap)
-{
- struct cap_rights_limit_args ap;
-
- ap.fd = uap->fd;
- ap.rights = PAIR32TO64(uint64_t, uap->rights);
- return (sys_cap_rights_limit(td, &ap));
-}
-
-int
freebsd32_cap_ioctls_limit(struct thread *td,
struct freebsd32_cap_ioctls_limit_args *uap)
{
@@ -148,14 +136,6 @@ out:
#else /* !CAPABILITIES */
int
-freebsd32_cap_rights_limit(struct thread *td,
- struct freebsd32_cap_rights_limit_args *uap)
-{
-
- return (ENOSYS);
-}
-
-int
freebsd32_cap_ioctls_limit(struct thread *td,
struct freebsd32_cap_ioctls_limit_args *uap)
{
diff --git a/sys/compat/freebsd32/freebsd32_ioctl.c b/sys/compat/freebsd32/freebsd32_ioctl.c
index 81f5c8e..1f90e58 100644
--- a/sys/compat/freebsd32/freebsd32_ioctl.c
+++ b/sys/compat/freebsd32/freebsd32_ioctl.c
@@ -353,9 +353,11 @@ freebsd32_ioctl(struct thread *td, struct freebsd32_ioctl_args *uap)
caddr_t data;
}*/ ;
struct file *fp;
+ cap_rights_t rights;
int error;
- if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
fdrop(fp, td);
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c
index 16d1205..a3cf5cf 100644
--- a/sys/compat/freebsd32/freebsd32_misc.c
+++ b/sys/compat/freebsd32/freebsd32_misc.c
@@ -1650,6 +1650,7 @@ freebsd32_do_sendfile(struct thread *td,
struct uio *hdr_uio, *trl_uio;
struct iovec32 *iov32;
struct file *fp;
+ cap_rights_t rights;
off_t offset;
int error;
@@ -1686,8 +1687,10 @@ freebsd32_do_sendfile(struct thread *td,
AUDIT_ARG_FD(uap->fd);
- if ((error = fget_read(td, uap->fd, CAP_PREAD, &fp)) != 0)
+ if ((error = fget_read(td, uap->fd,
+ cap_rights_init(&rights, CAP_PREAD), &fp)) != 0) {
goto out;
+ }
error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, offset,
uap->nbytes, uap->sbytes, uap->flags, compat ? SFK_COMPAT : 0, td);
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index a2e3e78..f537a54 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -970,9 +970,9 @@
512 AUE_SHMCTL NOSTD { int freebsd32_shmctl(int shmid, int cmd, \
struct shmid_ds32 *buf); }
513 AUE_LPATHCONF NOPROTO { int lpathconf(char *path, int name); }
-514 AUE_CAP_NEW NOPROTO { int cap_new(int fd, uint64_t rights); }
-515 AUE_CAP_RIGHTS_GET NOPROTO { int cap_rights_get(int fd, \
- uint64_t *rightsp); }
+514 AUE_NULL OBSOL cap_new
+515 AUE_CAP_RIGHTS_GET NOPROTO { int __cap_rights_get(int version, \
+ int fd, cap_rights_t *rightsp); }
516 AUE_CAP_ENTER NOPROTO { int cap_enter(void); }
517 AUE_CAP_GETMODE NOPROTO { int cap_getmode(u_int *modep); }
518 AUE_PDFORK NOPROTO { int pdfork(int *fdp, int flags); }
@@ -1016,10 +1016,6 @@
int *status, int options, \
struct wrusage32 *wrusage, \
siginfo_t *info); }
-533 AUE_CAP_RIGHTS_LIMIT STD { \
- int freebsd32_cap_rights_limit(int fd, \
- int pad, \
- uint32_t rights1, uint32_t rights2); }
#else
530 AUE_NULL STD { int freebsd32_posix_fallocate(int fd,\
uint32_t offset1, uint32_t offset2,\
@@ -1033,10 +1029,10 @@
int *status, int options, \
struct wrusage32 *wrusage, \
siginfo_t *info); }
-533 AUE_CAP_RIGHTS_LIMIT STD { \
- int freebsd32_cap_rights_limit(int fd, \
- uint32_t rights1, uint32_t rights2); }
#endif
+533 AUE_CAP_RIGHTS_LIMIT NOPROTO { \
+ int cap_rights_limit(int fd, \
+ cap_rights_t *rightsp); }
534 AUE_CAP_IOCTLS_LIMIT STD { \
int freebsd32_cap_ioctls_limit(int fd, \
const uint32_t *cmds, size_t ncmds); }
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 49c3fdf..a6b1d35 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -92,6 +92,7 @@ linux_creat(struct thread *td, struct linux_creat_args *args)
static int
linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mode)
{
+ cap_rights_t rights;
struct proc *p = td->td_proc;
struct file *fp;
int fd;
@@ -143,7 +144,7 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod
* having the same filedesc could use that fd without
* checking below.
*/
- error = fget(td, fd, CAP_IOCTL, &fp);
+ error = fget(td, fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
if (!error) {
sx_slock(&proctree_lock);
PROC_LOCK(p);
@@ -328,6 +329,7 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
caddr_t outp; /* Linux-format */
int resid, linuxreclen=0; /* Linux-format */
caddr_t lbuf; /* Linux-format */
+ cap_rights_t rights;
struct file *fp;
struct uio auio;
struct iovec aiov;
@@ -348,7 +350,9 @@ getdents_common(struct thread *td, struct linux_getdents64_args *args,
} else
justone = 0;
- if ((error = getvnode(td->td_proc->p_fd, args->fd, CAP_READ, &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, args->fd,
+ cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
@@ -1024,6 +1028,7 @@ linux_pread(td, uap)
struct linux_pread_args *uap;
{
struct pread_args bsd;
+ cap_rights_t rights;
struct vnode *vp;
int error;
@@ -1036,7 +1041,9 @@ linux_pread(td, uap)
if (error == 0) {
/* This seems to violate POSIX but linux does it */
- if ((error = fgetvp(td, uap->fd, CAP_PREAD, &vp)) != 0)
+ error = fgetvp(td, uap->fd,
+ cap_rights_init(&rights, CAP_PREAD), &vp);
+ if (error != 0)
return (error);
if (vp->v_type == VDIR) {
vrele(vp);
@@ -1283,6 +1290,7 @@ fcntl_common(struct thread *td, struct linux_fcntl64_args *args)
{
struct l_flock linux_flock;
struct flock bsd_flock;
+ cap_rights_t rights;
struct file *fp;
long arg;
int error, result;
@@ -1385,7 +1393,8 @@ fcntl_common(struct thread *td, struct linux_fcntl64_args *args)
* significant effect for pipes (SIGIO is not delivered for
* pipes under Linux-2.2.35 at least).
*/
- error = fget(td, args->fd, CAP_FCNTL, &fp);
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_FCNTL), &fp);
if (error)
return (error);
if (fp->f_type == DTYPE_PIPE) {
diff --git a/sys/compat/linux/linux_ioctl.c b/sys/compat/linux/linux_ioctl.c
index 4df28aa..2a4016a 100644
--- a/sys/compat/linux/linux_ioctl.c
+++ b/sys/compat/linux/linux_ioctl.c
@@ -189,12 +189,14 @@ struct linux_hd_big_geometry {
static int
linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error;
u_int sectorsize, fwcylinders, fwheads, fwsectors;
off_t mediasize, bytespercyl;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
switch (args->cmd & 0xffff) {
case LINUX_HDIO_GET_GEO:
@@ -270,12 +272,14 @@ linux_ioctl_hdio(struct thread *td, struct linux_ioctl_args *args)
static int
linux_ioctl_disk(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error;
u_int sectorsize;
off_t mediasize;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
switch (args->cmd & 0xffff) {
case LINUX_BLKGETSIZE:
@@ -698,10 +702,12 @@ linux_ioctl_termio(struct thread *td, struct linux_ioctl_args *args)
struct termios bios;
struct linux_termios lios;
struct linux_termio lio;
+ cap_rights_t rights;
struct file *fp;
int error;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
switch (args->cmd & 0xffff) {
@@ -1438,10 +1444,12 @@ bsd_to_linux_dvd_authinfo(struct dvd_authinfo *bp, l_dvd_authinfo *lp)
static int
linux_ioctl_cdrom(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
switch (args->cmd & 0xffff) {
@@ -1963,10 +1971,12 @@ linux_ioctl_sound(struct thread *td, struct linux_ioctl_args *args)
static int
linux_ioctl_console(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
switch (args->cmd & 0xffff) {
@@ -2351,6 +2361,7 @@ static int
linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
{
char lifname[LINUX_IFNAMSIZ], ifname[IFNAMSIZ];
+ cap_rights_t rights;
struct ifnet *ifp;
struct file *fp;
int error, type;
@@ -2358,7 +2369,8 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
ifp = NULL;
error = 0;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
type = fp->f_type;
fdrop(fp, td);
@@ -2581,10 +2593,12 @@ linux_ioctl_socket(struct thread *td, struct linux_ioctl_args *args)
static int
linux_ioctl_private(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error, type;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
type = fp->f_type;
fdrop(fp, td);
@@ -2606,11 +2620,13 @@ linux_ioctl_drm(struct thread *td, struct linux_ioctl_args *args)
static int
linux_ioctl_sg(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
u_long cmd;
int error;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0) {
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0) {
printf("sg_linux_ioctl: fget returned %d\n", error);
return (error);
}
@@ -2828,6 +2844,7 @@ linux_v4l_cliplist_copy(struct l_video_window *lvw, struct video_window *vw)
static int
linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error;
struct video_tuner vtun;
@@ -2845,7 +2862,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
case LINUX_VIDIOCSCHAN: args->cmd = VIDIOCSCHAN; break;
case LINUX_VIDIOCGTUNER:
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
if (error) {
@@ -2863,7 +2882,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
case LINUX_VIDIOCSTUNER:
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = copyin((void *) args->arg, &l_vtun, sizeof(l_vtun));
if (error) {
@@ -2880,7 +2901,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
case LINUX_VIDIOCCAPTURE: args->cmd = VIDIOCCAPTURE; break;
case LINUX_VIDIOCGWIN:
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = fo_ioctl(fp, VIDIOCGWIN, &vwin, td->td_ucred, td);
if (!error) {
@@ -2892,7 +2915,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
case LINUX_VIDIOCSWIN:
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = copyin((void *) args->arg, &l_vwin, sizeof(l_vwin));
if (error) {
@@ -2915,7 +2940,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
case LINUX_VIDIOCGFBUF:
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = fo_ioctl(fp, VIDIOCGFBUF, &vbuf, td->td_ucred, td);
if (!error) {
@@ -2927,7 +2954,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
return (error);
case LINUX_VIDIOCSFBUF:
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = copyin((void *) args->arg, &l_vbuf, sizeof(l_vbuf));
if (error) {
@@ -2955,7 +2984,9 @@ linux_ioctl_v4l(struct thread *td, struct linux_ioctl_args *args)
case LINUX_VIDIOCGPLAYINFO: args->cmd = VIDIOCGPLAYINFO; break;
case LINUX_VIDIOCSMICROCODE:
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = copyin((void *) args->arg, &l_vcode, sizeof(l_vcode));
if (error) {
@@ -3108,6 +3139,7 @@ bsd_to_linux_v4l2_format(struct v4l2_format *vf, struct l_v4l2_format *lvf)
static int
linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error;
struct v4l2_format vformat;
@@ -3199,7 +3231,9 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
error = copyin((void *)args->arg, &l_vformat, sizeof(l_vformat));
if (error)
return (error);
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error)
return (error);
if (linux_to_bsd_v4l2_format(&l_vformat, &vformat) != 0)
error = EINVAL;
@@ -3222,7 +3256,9 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
if (error)
return (error);
linux_to_bsd_v4l2_standard(&l_vstd, &vstd);
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error)
return (error);
error = fo_ioctl(fp, VIDIOC_ENUMSTD, (caddr_t)&vstd,
td->td_ucred, td);
@@ -3244,7 +3280,9 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
sizeof(struct l_v4l2_input));
if (error != 0)
return (error);
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = fo_ioctl(fp, VIDIOC_ENUMINPUT, (caddr_t)&vinp,
td->td_ucred, td);
@@ -3263,7 +3301,9 @@ linux_ioctl_v4l2(struct thread *td, struct linux_ioctl_args *args)
error = copyin((void *)args->arg, &l_vbuf, sizeof(l_vbuf));
if (error)
return (error);
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error)
return (error);
linux_to_bsd_v4l2_buffer(&l_vbuf, &vbuf);
if ((args->cmd & 0xffff) == LINUX_VIDIOC_QUERYBUF)
@@ -3432,6 +3472,7 @@ linux_ioctl_fbsd_usb(struct thread *td, struct linux_ioctl_args *args)
int
linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
struct handler_element *he;
int error, cmd;
@@ -3442,7 +3483,8 @@ linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
(unsigned long)args->cmd);
#endif
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & (FREAD|FWRITE)) == 0) {
fdrop(fp, td);
diff --git a/sys/compat/linux/linux_socket.c b/sys/compat/linux/linux_socket.c
index 36b23ac..22f811c 100644
--- a/sys/compat/linux/linux_socket.c
+++ b/sys/compat/linux/linux_socket.c
@@ -748,6 +748,7 @@ int linux_connect(struct thread *, struct linux_connect_args *);
int
linux_connect(struct thread *td, struct linux_connect_args *args)
{
+ cap_rights_t rights;
struct socket *so;
struct sockaddr *sa;
u_int fflag;
@@ -772,7 +773,8 @@ linux_connect(struct thread *td, struct linux_connect_args *args)
* socket and use the file descriptor reference instead of
* creating a new one.
*/
- error = fgetsock(td, args->s, CAP_CONNECT, &so, &fflag);
+ error = fgetsock(td, args->s, cap_rights_init(&rights, CAP_CONNECT),
+ &so, &fflag);
if (error == 0) {
error = EISCONN;
if (fflag & FNONBLOCK) {
diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c
index 86fab78..8d0b715 100644
--- a/sys/compat/svr4/svr4_fcntl.c
+++ b/sys/compat/svr4/svr4_fcntl.c
@@ -259,6 +259,7 @@ fd_revoke(td, fd)
struct vnode *vp;
struct mount *mp;
struct vattr vattr;
+ cap_rights_t rights;
int error, *retval;
retval = td->td_retval;
@@ -267,12 +268,13 @@ fd_revoke(td, fd)
* or FreeBSD grows a native frevoke() (more likely), we will need a
* CAP_FREVOKE here.
*
- * In the meantime, use CAP_ALL: if a SVR4 process wants to
+ * In the meantime, use CAP_ALL(): if a SVR4 process wants to
* do an frevoke(), it needs to do it on either a regular file
* descriptor or a fully-privileged capability (which is effectively
* the same as a non-capability-restricted file descriptor).
*/
- if ((error = fgetvp(td, fd, CAP_ALL, &vp)) != 0)
+ CAP_ALL(&rights);
+ if ((error = fgetvp(td, fd, &rights, &vp)) != 0)
return (error);
if (vp->v_type != VCHR && vp->v_type != VBLK) {
@@ -318,13 +320,15 @@ fd_truncate(td, fd, flp)
struct vattr vattr;
int error, *retval;
struct ftruncate_args ft;
+ cap_rights_t rights;
retval = td->td_retval;
/*
* We only support truncating the file.
*/
- if ((error = fget(td, fd, CAP_FTRUNCATE, &fp)) != 0)
+ error = fget(td, fd, cap_rights_init(&rights, CAP_FTRUNCATE), &fp);
+ if (error != 0)
return (error);
vp = fp->f_vnode;
@@ -401,9 +405,11 @@ svr4_sys_open(td, uap)
if (!(bsd_flags & O_NOCTTY) && SESS_LEADER(p) &&
!(p->p_flag & P_CONTROLT)) {
#if defined(NOTYET)
- struct file *fp;
+ cap_rights_t rights;
+ struct file *fp;
- error = fget(td, retval, CAP_IOCTL, &fp);
+ error = fget(td, retval,
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
PROC_UNLOCK(p);
/*
* we may have lost a race the above open() and
diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c
index 0fbba07..b953e72 100644
--- a/sys/compat/svr4/svr4_filio.c
+++ b/sys/compat/svr4/svr4_filio.c
@@ -104,6 +104,7 @@ svr4_sys_read(td, uap)
struct svr4_sys_read_args *uap;
{
struct read_args ra;
+ cap_rights_t rights;
struct file *fp;
struct socket *so = NULL;
int so_state;
@@ -114,7 +115,7 @@ svr4_sys_read(td, uap)
ra.buf = uap->buf;
ra.nbyte = uap->nbyte;
- if (fget(td, uap->fd, CAP_READ, &fp) != 0) {
+ if (fget(td, uap->fd, cap_rights_init(&rights, CAP_READ), &fp) != 0) {
DPRINTF(("Something fishy with the user-supplied file descriptor...\n"));
return EBADF;
}
diff --git a/sys/compat/svr4/svr4_ioctl.c b/sys/compat/svr4/svr4_ioctl.c
index 36b0580..a8c8c8c 100644
--- a/sys/compat/svr4/svr4_ioctl.c
+++ b/sys/compat/svr4/svr4_ioctl.c
@@ -84,6 +84,7 @@ svr4_sys_ioctl(td, uap)
struct svr4_sys_ioctl_args *uap;
{
int *retval;
+ cap_rights_t rights;
struct file *fp;
u_long cmd;
int (*fun)(struct file *, struct thread *, register_t *,
@@ -103,7 +104,8 @@ svr4_sys_ioctl(td, uap)
retval = td->td_retval;
cmd = uap->com;
- if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index 0cfaeae..4888698 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -236,6 +236,7 @@ svr4_sys_getdents64(td, uap)
int len, reclen; /* BSD-format */
caddr_t outp; /* SVR4-format */
int resid, svr4reclen=0; /* SVR4-format */
+ cap_rights_t rights;
struct file *fp;
struct uio auio;
struct iovec aiov;
@@ -247,7 +248,9 @@ svr4_sys_getdents64(td, uap)
DPRINTF(("svr4_sys_getdents64(%d, *, %d)\n",
uap->fd, uap->nbytes));
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
@@ -412,6 +415,7 @@ svr4_sys_getdents(td, uap)
int len, reclen; /* BSD-format */
caddr_t outp; /* SVR4-format */
int resid, svr4_reclen; /* SVR4-format */
+ cap_rights_t rights;
struct file *fp;
struct uio auio;
struct iovec aiov;
@@ -424,7 +428,9 @@ svr4_sys_getdents(td, uap)
if (uap->nbytes < 0)
return (EINVAL);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
diff --git a/sys/compat/svr4/svr4_stream.c b/sys/compat/svr4/svr4_stream.c
index 1c7e83e..6348b9b 100644
--- a/sys/compat/svr4/svr4_stream.c
+++ b/sys/compat/svr4/svr4_stream.c
@@ -1446,10 +1446,12 @@ svr4_sys_putmsg(td, uap)
struct thread *td;
struct svr4_sys_putmsg_args *uap;
{
- struct file *fp;
+ cap_rights_t rights;
+ struct file *fp;
int error;
- if ((error = fget(td, uap->fd, CAP_SEND, &fp)) != 0) {
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_SEND), &fp);
+ if (error != 0) {
#ifdef DEBUG_SVR4
uprintf("putmsg: bad fp\n");
#endif
@@ -1618,10 +1620,12 @@ svr4_sys_getmsg(td, uap)
struct thread *td;
struct svr4_sys_getmsg_args *uap;
{
- struct file *fp;
+ cap_rights_t rights;
+ struct file *fp;
int error;
- if ((error = fget(td, uap->fd, CAP_RECV, &fp)) != 0) {
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_RECV), &fp);
+ if (error != 0) {
#ifdef DEBUG_SVR4
uprintf("getmsg: bad fp\n");
#endif
diff --git a/sys/conf/files b/sys/conf/files
index f02944f..8bb4eff 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -2847,6 +2847,7 @@ kern/subr_blist.c standard
kern/subr_bus.c standard
kern/subr_bus_dma.c standard
kern/subr_bufring.c standard
+kern/subr_capability.c standard
kern/subr_clock.c standard
kern/subr_counter.c standard
kern/subr_devstat.c standard
diff --git a/sys/dev/aac/aac_linux.c b/sys/dev/aac/aac_linux.c
index 049e2be..591dfbb 100644
--- a/sys/dev/aac/aac_linux.c
+++ b/sys/dev/aac/aac_linux.c
@@ -75,11 +75,13 @@ MODULE_DEPEND(aac_linux, linux, 1, 1, 1);
static int
aac_linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
u_long cmd;
int error;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
cmd = args->cmd;
diff --git a/sys/dev/amr/amr_linux.c b/sys/dev/amr/amr_linux.c
index 44e858b..5b1a17f 100644
--- a/sys/dev/amr/amr_linux.c
+++ b/sys/dev/amr/amr_linux.c
@@ -72,10 +72,12 @@ MODULE_DEPEND(amr, linux, 1, 1, 1);
static int
amr_linux_ioctl(struct thread *p, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error;
- if ((error = fget(p, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(p, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p);
fdrop(fp, p);
diff --git a/sys/dev/filemon/filemon.c b/sys/dev/filemon/filemon.c
index ce84e3d..e3fda18 100644
--- a/sys/dev/filemon/filemon.c
+++ b/sys/dev/filemon/filemon.c
@@ -138,12 +138,6 @@ filemon_dtr(void *data)
}
}
-#if __FreeBSD_version < 900041
-#define FGET_WRITE(a1, a2, a3) fget_write((a1), (a2), (a3))
-#else
-#define FGET_WRITE(a1, a2, a3) fget_write((a1), (a2), CAP_WRITE | CAP_SEEK, (a3))
-#endif
-
static int
filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
struct thread *td)
@@ -151,13 +145,21 @@ filemon_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag __unused,
int error = 0;
struct filemon *filemon;
struct proc *p;
+#if __FreeBSD_version >= 900041
+ cap_rights_t rights;
+#endif
devfs_get_cdevpriv((void **) &filemon);
switch (cmd) {
/* Set the output file descriptor. */
case FILEMON_SET_FD:
- if ((error = FGET_WRITE(td, *(int *)data, &filemon->fp)) == 0)
+ error = fget_write(td, *(int *)data,
+#if __FreeBSD_version >= 900041
+ cap_rights_init(&rights, CAP_PWRITE),
+#endif
+ &filemon->fp);
+ if (error == 0)
/* Write the file header. */
filemon_comment(filemon);
break;
diff --git a/sys/dev/hwpmc/hwpmc_logging.c b/sys/dev/hwpmc/hwpmc_logging.c
index 880bcaa..a60e096 100644
--- a/sys/dev/hwpmc/hwpmc_logging.c
+++ b/sys/dev/hwpmc/hwpmc_logging.c
@@ -570,6 +570,7 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
{
int error;
struct proc *p;
+ cap_rights_t rights;
/*
* As long as it is possible to get a LOR between pmc_sx lock and
@@ -593,7 +594,8 @@ pmclog_configure_log(struct pmc_mdep *md, struct pmc_owner *po, int logfd)
po->po_file));
/* get a reference to the file state */
- error = fget_write(curthread, logfd, CAP_WRITE, &po->po_file);
+ error = fget_write(curthread, logfd,
+ cap_rights_init(&rights, CAP_WRITE), &po->po_file);
if (error)
goto error;
diff --git a/sys/dev/ipmi/ipmi_linux.c b/sys/dev/ipmi/ipmi_linux.c
index 430bd08..b6b38f2 100644
--- a/sys/dev/ipmi/ipmi_linux.c
+++ b/sys/dev/ipmi/ipmi_linux.c
@@ -89,11 +89,13 @@ MODULE_DEPEND(ipmi_linux, linux, 1, 1, 1);
static int
ipmi_linux_ioctl(struct thread *td, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
u_long cmd;
int error;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
cmd = args->cmd;
diff --git a/sys/dev/iscsi_initiator/iscsi.c b/sys/dev/iscsi_initiator/iscsi.c
index 4dbf163..4a1cb96 100644
--- a/sys/dev/iscsi_initiator/iscsi.c
+++ b/sys/dev/iscsi_initiator/iscsi.c
@@ -382,16 +382,19 @@ i_ping(struct cdev *dev)
static int
i_setsoc(isc_session_t *sp, int fd, struct thread *td)
{
+ cap_rights_t rights;
int error = 0;
if(sp->soc != NULL)
isc_stop_receiver(sp);
- error = fget(td, fd, CAP_SOCK_CLIENT, &sp->fp);
+ error = fget(td, fd, cap_rights_init(&rights, CAP_SOCK_CLIENT), &sp->fp);
if(error)
return error;
- if((error = fgetsock(td, fd, CAP_SOCK_CLIENT, &sp->soc, 0)) == 0) {
+ error = fgetsock(td, fd, cap_rights_init(&rights, CAP_SOCK_CLIENT),
+ &sp->soc, 0);
+ if(error == 0) {
sp->td = td;
isc_start_receiver(sp);
}
diff --git a/sys/dev/mfi/mfi_linux.c b/sys/dev/mfi/mfi_linux.c
index 3328a66..429d496 100644
--- a/sys/dev/mfi/mfi_linux.c
+++ b/sys/dev/mfi/mfi_linux.c
@@ -84,6 +84,7 @@ MODULE_DEPEND(mfi, linux, 1, 1, 1);
static int
mfi_linux_ioctl(struct thread *p, struct linux_ioctl_args *args)
{
+ cap_rights_t rights;
struct file *fp;
int error;
u_long cmd = args->cmd;
@@ -97,7 +98,8 @@ mfi_linux_ioctl(struct thread *p, struct linux_ioctl_args *args)
break;
}
- if ((error = fget(p, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(p, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
error = fo_ioctl(fp, cmd, (caddr_t)args->arg, p->td_ucred, p);
fdrop(fp, p);
diff --git a/sys/dev/tdfx/tdfx_linux.c b/sys/dev/tdfx/tdfx_linux.c
index 0b769f0..fa39ab1 100644
--- a/sys/dev/tdfx/tdfx_linux.c
+++ b/sys/dev/tdfx/tdfx_linux.c
@@ -45,6 +45,7 @@ LINUX_IOCTL_SET(tdfx, LINUX_IOCTL_TDFX_MIN, LINUX_IOCTL_TDFX_MAX);
static int
linux_ioctl_tdfx(struct thread *td, struct linux_ioctl_args* args)
{
+ cap_rights_t rights;
int error = 0;
u_long cmd = args->cmd & 0xffff;
@@ -54,7 +55,8 @@ linux_ioctl_tdfx(struct thread *td, struct linux_ioctl_args* args)
struct file *fp;
- if ((error = fget(td, args->fd, CAP_IOCTL, &fp)) != 0)
+ error = fget(td, args->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0)
return (error);
/* We simply copy the data and send it right to ioctl */
copyin((caddr_t)args->arg, &d_pio, sizeof(d_pio));
diff --git a/sys/fs/fdescfs/fdesc_vnops.c b/sys/fs/fdescfs/fdesc_vnops.c
index f18c0fc..fe939b1 100644
--- a/sys/fs/fdescfs/fdesc_vnops.c
+++ b/sys/fs/fdescfs/fdesc_vnops.c
@@ -445,6 +445,7 @@ fdesc_setattr(ap)
struct mount *mp;
struct file *fp;
struct thread *td = curthread;
+ cap_rights_t rights;
unsigned fd;
int error;
@@ -459,7 +460,8 @@ fdesc_setattr(ap)
/*
* Allow setattr where there is an underlying vnode.
*/
- error = getvnode(td->td_proc->p_fd, fd, CAP_EXTATTR_SET, &fp);
+ error = getvnode(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_EXTATTR_SET), &fp);
if (error) {
/*
* getvnode() returns EINVAL if the file descriptor is not
diff --git a/sys/fs/fuse/fuse_vfsops.c b/sys/fs/fuse/fuse_vfsops.c
index 639550a..0b4f19b 100644
--- a/sys/fs/fuse/fuse_vfsops.c
+++ b/sys/fs/fuse/fuse_vfsops.c
@@ -220,6 +220,7 @@ fuse_vfsop_mount(struct mount *mp)
struct file *fp, *fptmp;
char *fspec, *subtype;
struct vfsoptlist *opts;
+ cap_rights_t rights;
subtype = NULL;
max_read_set = 0;
@@ -289,7 +290,7 @@ fuse_vfsop_mount(struct mount *mp)
FS_DEBUG2G("mntopts 0x%jx\n", (uintmax_t)mntopts);
- err = fget(td, fd, CAP_READ, &fp);
+ err = fget(td, fd, cap_rights_init(&rights, CAP_READ), &fp);
if (err != 0) {
FS_DEBUG("invalid or not opened device: data=%p\n", data);
goto out;
diff --git a/sys/fs/nfsclient/nfs_clport.c b/sys/fs/nfsclient/nfs_clport.c
index d7b082b..b198d59 100644
--- a/sys/fs/nfsclient/nfs_clport.c
+++ b/sys/fs/nfsclient/nfs_clport.c
@@ -1219,10 +1219,11 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap)
struct file *fp;
struct nfscbd_args nfscbdarg;
struct nfsd_nfscbd_args nfscbdarg2;
- int error;
struct nameidata nd;
struct nfscl_dumpmntopts dumpmntopts;
+ cap_rights_t rights;
char *buf;
+ int error;
if (uap->flag & NFSSVC_CBADDSOCK) {
error = copyin(uap->argp, (caddr_t)&nfscbdarg, sizeof(nfscbdarg));
@@ -1233,10 +1234,10 @@ nfssvc_nfscl(struct thread *td, struct nfssvc_args *uap)
* pretend that we need them all. It is better to be too
* careful than too reckless.
*/
- if ((error = fget(td, nfscbdarg.sock, CAP_SOCK_CLIENT, &fp))
- != 0) {
+ error = fget(td, nfscbdarg.sock,
+ cap_rights_init(&rights, CAP_SOCK_CLIENT), &fp);
+ if (error)
return (error);
- }
if (fp->f_type != DTYPE_SOCKET) {
fdrop(fp, td);
return (EPERM);
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index a6a0169..2f9d40a 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -3035,6 +3035,7 @@ nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap)
struct file *fp;
struct nfsd_addsock_args sockarg;
struct nfsd_nfsd_args nfsdarg;
+ cap_rights_t rights;
int error;
if (uap->flag & NFSSVC_NFSDADDSOCK) {
@@ -3046,7 +3047,9 @@ nfssvc_nfsd(struct thread *td, struct nfssvc_args *uap)
* pretend that we need them all. It is better to be too
* careful than too reckless.
*/
- if ((error = fget(td, sockarg.sock, CAP_SOCK_SERVER, &fp)) != 0)
+ error = fget(td, sockarg.sock,
+ cap_rights_init(&rights, CAP_SOCK_SERVER), &fp);
+ if (error != 0)
goto out;
if (fp->f_type != DTYPE_SOCKET) {
fdrop(fp, td);
diff --git a/sys/i386/ibcs2/ibcs2_fcntl.c b/sys/i386/ibcs2/ibcs2_fcntl.c
index 2902da7..d061b79 100644
--- a/sys/i386/ibcs2/ibcs2_fcntl.c
+++ b/sys/i386/ibcs2/ibcs2_fcntl.c
@@ -201,10 +201,12 @@ ibcs2_open(td, uap)
free(path, M_TEMP);
PROC_LOCK(p);
if (!ret && !noctty && SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
+ cap_rights_t rights;
struct file *fp;
int error;
- error = fget(td, td->td_retval[0], CAP_IOCTL, &fp);
+ error = fget(td, td->td_retval[0],
+ cap_rights_init(&rights, CAP_IOCTL), &fp);
PROC_UNLOCK(p);
if (error)
return (EBADF);
diff --git a/sys/i386/ibcs2/ibcs2_ioctl.c b/sys/i386/ibcs2/ibcs2_ioctl.c
index 83e68cd..03fa5f6 100644
--- a/sys/i386/ibcs2/ibcs2_ioctl.c
+++ b/sys/i386/ibcs2/ibcs2_ioctl.c
@@ -331,10 +331,12 @@ ibcs2_ioctl(td, uap)
struct ibcs2_ioctl_args *uap;
{
struct proc *p = td->td_proc;
+ cap_rights_t rights;
struct file *fp;
int error;
- if ((error = fget(td, uap->fd, CAP_IOCTL, &fp)) != 0) {
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0) {
DPRINTF(("ibcs2_ioctl(%d): bad fd %d ", p->p_pid,
uap->fd));
return EBADF;
diff --git a/sys/i386/ibcs2/ibcs2_misc.c b/sys/i386/ibcs2/ibcs2_misc.c
index 9f382aa..28cd83c 100644
--- a/sys/i386/ibcs2/ibcs2_misc.c
+++ b/sys/i386/ibcs2/ibcs2_misc.c
@@ -326,6 +326,7 @@ ibcs2_getdents(td, uap)
register int len, reclen; /* BSD-format */
register caddr_t outp; /* iBCS2-format */
register int resid; /* iBCS2-format */
+ cap_rights_t rights;
struct file *fp;
struct uio auio;
struct iovec aiov;
@@ -337,7 +338,9 @@ ibcs2_getdents(td, uap)
#define BSD_DIRENT(cp) ((struct dirent *)(cp))
#define IBCS2_RECLEN(reclen) (reclen + sizeof(u_short))
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
fdrop(fp, td);
@@ -478,6 +481,7 @@ ibcs2_read(td, uap)
register int len, reclen; /* BSD-format */
register caddr_t outp; /* iBCS2-format */
register int resid; /* iBCS2-format */
+ cap_rights_t rights;
struct file *fp;
struct uio auio;
struct iovec aiov;
@@ -490,8 +494,9 @@ ibcs2_read(td, uap)
u_long *cookies = NULL, *cookiep;
int ncookies;
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ,
- &fp)) != 0) {
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0) {
if (error == EINVAL)
return sys_read(td, (struct read_args *)uap);
else
diff --git a/sys/i386/linux/linux_machdep.c b/sys/i386/linux/linux_machdep.c
index 14d1892..2d79204 100644
--- a/sys/i386/linux/linux_machdep.c
+++ b/sys/i386/linux/linux_machdep.c
@@ -422,6 +422,7 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
} */ bsd_args;
int error;
struct file *fp;
+ cap_rights_t rights;
error = 0;
bsd_args.flags = 0;
@@ -473,7 +474,9 @@ linux_mmap_common(struct thread *td, l_uintptr_t addr, l_size_t len, l_int prot,
* is done in the FreeBSD mmap().
*/
- if ((error = fget(td, bsd_args.fd, CAP_MMAP, &fp)) != 0)
+ error = fget(td, bsd_args.fd,
+ cap_rights_init(&rights, CAP_MMAP), &fp);
+ if (error != 0)
return (error);
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
diff --git a/sys/kern/capabilities.conf b/sys/kern/capabilities.conf
index d2fa51c..eaa5b14 100644
--- a/sys/kern/capabilities.conf
+++ b/sys/kern/capabilities.conf
@@ -114,8 +114,7 @@ cap_fcntls_limit
cap_getmode
cap_ioctls_get
cap_ioctls_limit
-cap_new
-cap_rights_get
+__cap_rights_get
cap_rights_limit
##
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index d0de6b9..a0545e1 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -455,6 +455,7 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
struct filedescent *fde;
struct proc *p;
struct vnode *vp;
+ cap_rights_t rights;
int error, flg, tmp;
u_int old, new;
uint64_t bsize;
@@ -515,7 +516,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
break;
case F_GETFL:
- error = fget_unlocked(fdp, fd, CAP_FCNTL, F_GETFL, &fp, NULL);
+ error = fget_unlocked(fdp, fd,
+ cap_rights_init(&rights, CAP_FCNTL), F_GETFL, &fp, NULL);
if (error != 0)
break;
td->td_retval[0] = OFLAGS(fp->f_flag);
@@ -523,7 +525,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
break;
case F_SETFL:
- error = fget_unlocked(fdp, fd, CAP_FCNTL, F_SETFL, &fp, NULL);
+ error = fget_unlocked(fdp, fd,
+ cap_rights_init(&rights, CAP_FCNTL), F_SETFL, &fp, NULL);
if (error != 0)
break;
do {
@@ -550,7 +553,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
break;
case F_GETOWN:
- error = fget_unlocked(fdp, fd, CAP_FCNTL, F_GETOWN, &fp, NULL);
+ error = fget_unlocked(fdp, fd,
+ cap_rights_init(&rights, CAP_FCNTL), F_GETOWN, &fp, NULL);
if (error != 0)
break;
error = fo_ioctl(fp, FIOGETOWN, &tmp, td->td_ucred, td);
@@ -560,7 +564,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
break;
case F_SETOWN:
- error = fget_unlocked(fdp, fd, CAP_FCNTL, F_SETOWN, &fp, NULL);
+ error = fget_unlocked(fdp, fd,
+ cap_rights_init(&rights, CAP_FCNTL), F_SETOWN, &fp, NULL);
if (error != 0)
break;
tmp = arg;
@@ -581,7 +586,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
case F_SETLK:
do_setlk:
- error = fget_unlocked(fdp, fd, CAP_FLOCK, 0, &fp, NULL);
+ error = fget_unlocked(fdp, fd,
+ cap_rights_init(&rights, CAP_FLOCK), 0, &fp, NULL);
if (error != 0)
break;
if (fp->f_type != DTYPE_VNODE) {
@@ -688,7 +694,8 @@ kern_fcntl(struct thread *td, int fd, int cmd, intptr_t arg)
break;
case F_GETLK:
- error = fget_unlocked(fdp, fd, CAP_FLOCK, 0, &fp, NULL);
+ error = fget_unlocked(fdp, fd,
+ cap_rights_init(&rights, CAP_FLOCK), 0, &fp, NULL);
if (error != 0)
break;
if (fp->f_type != DTYPE_VNODE) {
@@ -1281,11 +1288,13 @@ int
kern_fstat(struct thread *td, int fd, struct stat *sbp)
{
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(fd);
- if ((error = fget(td, fd, CAP_FSTAT, &fp)) != 0)
+ error = fget(td, fd, cap_rights_init(&rights, CAP_FSTAT), &fp);
+ if (error != 0)
return (error);
AUDIT_ARG_FILE(td->td_proc, fp);
@@ -1339,9 +1348,11 @@ sys_fpathconf(struct thread *td, struct fpathconf_args *uap)
{
struct file *fp;
struct vnode *vp;
+ cap_rights_t rights;
int error;
- if ((error = fget(td, uap->fd, CAP_FPATHCONF, &fp)) != 0)
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FPATHCONF), &fp);
+ if (error != 0)
return (error);
/* If asynchronous I/O is available, it works for all descriptors. */
@@ -1417,7 +1428,7 @@ static void
filecaps_fill(struct filecaps *fcaps)
{
- fcaps->fc_rights = CAP_ALL;
+ CAP_ALL(&fcaps->fc_rights);
fcaps->fc_ioctls = NULL;
fcaps->fc_nioctls = -1;
fcaps->fc_fcntls = CAP_FCNTL_ALL;
@@ -1441,16 +1452,18 @@ static void
filecaps_validate(const struct filecaps *fcaps, const char *func)
{
- KASSERT((fcaps->fc_rights & ~CAP_MASK_VALID) == 0,
+ KASSERT(cap_rights_is_valid(&fcaps->fc_rights),
("%s: invalid rights", func));
KASSERT((fcaps->fc_fcntls & ~CAP_FCNTL_ALL) == 0,
("%s: invalid fcntls", func));
- KASSERT(fcaps->fc_fcntls == 0 || (fcaps->fc_rights & CAP_FCNTL) != 0,
+ KASSERT(fcaps->fc_fcntls == 0 ||
+ cap_rights_is_set(&fcaps->fc_rights, CAP_FCNTL),
("%s: fcntls without CAP_FCNTL", func));
KASSERT(fcaps->fc_ioctls != NULL ? fcaps->fc_nioctls > 0 :
(fcaps->fc_nioctls == -1 || fcaps->fc_nioctls == 0),
("%s: invalid ioctls", func));
- KASSERT(fcaps->fc_nioctls == 0 || (fcaps->fc_rights & CAP_IOCTL) != 0,
+ KASSERT(fcaps->fc_nioctls == 0 ||
+ cap_rights_is_set(&fcaps->fc_rights, CAP_IOCTL),
("%s: ioctls without CAP_IOCTL", func));
}
@@ -2285,7 +2298,7 @@ finit(struct file *fp, u_int flag, short type, void *data, struct fileops *ops)
}
int
-fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights,
+fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
int needfcntl, struct file **fpp, cap_rights_t *haverightsp)
{
struct file *fp;
@@ -2310,11 +2323,11 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights,
if (fp == NULL)
return (EBADF);
#ifdef CAPABILITIES
- haverights = cap_rights(fdp, fd);
- error = cap_check(haverights, needrights);
+ haverights = *cap_rights(fdp, fd);
+ error = cap_check(&haverights, needrightsp);
if (error != 0)
return (error);
- if ((needrights & CAP_FCNTL) != 0) {
+ if (cap_rights_is_set(needrightsp, CAP_FCNTL)) {
error = cap_fcntl_check(fdp, fd, needfcntl);
if (error != 0)
return (error);
@@ -2338,7 +2351,7 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights,
#ifdef CAPABILITIES
*haverightsp = haverights;
#else
- *haverightsp = CAP_ALL;
+ CAP_ALL(haverightsp);
#endif
}
return (0);
@@ -2359,19 +2372,20 @@ fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights,
*/
static __inline int
_fget(struct thread *td, int fd, struct file **fpp, int flags,
- cap_rights_t needrights, u_char *maxprotp)
+ cap_rights_t *needrightsp, u_char *maxprotp)
{
struct filedesc *fdp;
struct file *fp;
- cap_rights_t haverights;
+ cap_rights_t haverights, needrights;
int error;
*fpp = NULL;
if (td == NULL || (fdp = td->td_proc->p_fd) == NULL)
return (EBADF);
+ needrights = *needrightsp;
if (maxprotp != NULL)
- needrights |= CAP_MMAP;
- error = fget_unlocked(fdp, fd, needrights, 0, &fp, &haverights);
+ cap_rights_set(&needrights, CAP_MMAP);
+ error = fget_unlocked(fdp, fd, &needrights, 0, &fp, &haverights);
if (error != 0)
return (error);
if (fp->f_ops == &badfileops) {
@@ -2384,7 +2398,7 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags,
* If requested, convert capability rights to access flags.
*/
if (maxprotp != NULL)
- *maxprotp = cap_rights_to_vmprot(haverights);
+ *maxprotp = cap_rights_to_vmprot(&haverights);
#else /* !CAPABILITIES */
if (maxprotp != NULL)
*maxprotp = VM_PROT_ALL;
@@ -2421,32 +2435,32 @@ _fget(struct thread *td, int fd, struct file **fpp, int flags,
}
int
-fget(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
+fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
{
- return(_fget(td, fd, fpp, 0, rights, NULL));
+ return(_fget(td, fd, fpp, 0, rightsp, NULL));
}
int
-fget_mmap(struct thread *td, int fd, cap_rights_t rights, u_char *maxprotp,
+fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp, u_char *maxprotp,
struct file **fpp)
{
- return (_fget(td, fd, fpp, 0, rights, maxprotp));
+ return (_fget(td, fd, fpp, 0, rightsp, maxprotp));
}
int
-fget_read(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
+fget_read(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
{
- return(_fget(td, fd, fpp, FREAD, rights, NULL));
+ return(_fget(td, fd, fpp, FREAD, rightsp, NULL));
}
int
-fget_write(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
+fget_write(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp)
{
- return (_fget(td, fd, fpp, FWRITE, rights, NULL));
+ return (_fget(td, fd, fpp, FWRITE, rightsp, NULL));
}
/*
@@ -2457,15 +2471,15 @@ fget_write(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
* XXX: what about the unused flags ?
*/
static __inline int
-_fgetvp(struct thread *td, int fd, int flags, cap_rights_t needrights,
+_fgetvp(struct thread *td, int fd, int flags, cap_rights_t *needrightsp,
struct vnode **vpp)
{
struct file *fp;
int error;
*vpp = NULL;
- error = _fget(td, fd, &fp, flags, needrights, NULL);
- if (error)
+ error = _fget(td, fd, &fp, flags, needrightsp, NULL);
+ if (error != 0)
return (error);
if (fp->f_vnode == NULL) {
error = EINVAL;
@@ -2479,14 +2493,14 @@ _fgetvp(struct thread *td, int fd, int flags, cap_rights_t needrights,
}
int
-fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
+fgetvp(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
{
- return (_fgetvp(td, fd, 0, rights, vpp));
+ return (_fgetvp(td, fd, 0, rightsp, vpp));
}
int
-fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
+fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp,
struct filecaps *havecaps, struct vnode **vpp)
{
struct filedesc *fdp;
@@ -2503,7 +2517,7 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
return (EBADF);
#ifdef CAPABILITIES
- error = cap_check(cap_rights(fdp, fd), need);
+ error = cap_check(cap_rights(fdp, fd), needrightsp);
if (error != 0)
return (error);
#endif
@@ -2519,26 +2533,26 @@ fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
}
int
-fgetvp_read(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
+fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
{
- return (_fgetvp(td, fd, FREAD, rights, vpp));
+ return (_fgetvp(td, fd, FREAD, rightsp, vpp));
}
int
-fgetvp_exec(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp)
+fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp, struct vnode **vpp)
{
- return (_fgetvp(td, fd, FEXEC, rights, vpp));
+ return (_fgetvp(td, fd, FEXEC, rightsp, vpp));
}
#ifdef notyet
int
-fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
+fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp,
struct vnode **vpp)
{
- return (_fgetvp(td, fd, FWRITE, rights, vpp));
+ return (_fgetvp(td, fd, FWRITE, rightsp, vpp));
}
#endif
@@ -2554,7 +2568,7 @@ fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
* during use.
*/
int
-fgetsock(struct thread *td, int fd, cap_rights_t rights, struct socket **spp,
+fgetsock(struct thread *td, int fd, cap_rights_t *rightsp, struct socket **spp,
u_int *fflagp)
{
struct file *fp;
@@ -2563,7 +2577,7 @@ fgetsock(struct thread *td, int fd, cap_rights_t rights, struct socket **spp,
*spp = NULL;
if (fflagp != NULL)
*fflagp = 0;
- if ((error = _fget(td, fd, &fp, 0, rights, NULL)) != 0)
+ if ((error = _fget(td, fd, &fp, 0, rightsp, NULL)) != 0)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
error = ENOTSOCK;
@@ -2637,9 +2651,11 @@ sys_flock(struct thread *td, struct flock_args *uap)
struct file *fp;
struct vnode *vp;
struct flock lf;
+ cap_rights_t rights;
int error;
- if ((error = fget(td, uap->fd, CAP_FLOCK, &fp)) != 0)
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FLOCK), &fp);
+ if (error != 0)
return (error);
if (fp->f_type != DTYPE_VNODE) {
fdrop(fp, td);
@@ -3185,7 +3201,7 @@ struct export_fd_buf {
static int
export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
- int64_t offset, cap_rights_t fd_cap_rights, struct export_fd_buf *efbuf)
+ int64_t offset, cap_rights_t *rightsp, struct export_fd_buf *efbuf)
{
struct {
int fflag;
@@ -3259,7 +3275,10 @@ export_fd_to_sb(void *data, int type, int fd, int fflags, int refcnt,
for (i = 0; i < NFFLAGS; i++)
if (fflags & fflags_table[i].fflag)
kif->kf_flags |= fflags_table[i].kf_fflag;
- kif->kf_cap_rights = fd_cap_rights;
+ if (rightsp != NULL)
+ kif->kf_cap_rights = *rightsp;
+ else
+ cap_rights_init(&kif->kf_cap_rights);
kif->kf_fd = fd;
kif->kf_type = type;
kif->kf_ref_count = refcnt;
@@ -3302,7 +3321,7 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
void *data;
int error, i;
int type, refcnt, fflags;
- cap_rights_t fd_cap_rights;
+ cap_rights_t rights;
PROC_LOCK_ASSERT(p, MA_OWNED);
@@ -3329,13 +3348,13 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
efbuf->remainder = maxlen;
if (tracevp != NULL)
export_fd_to_sb(tracevp, KF_TYPE_VNODE, KF_FD_TYPE_TRACE,
- FREAD | FWRITE, -1, -1, 0, efbuf);
+ FREAD | FWRITE, -1, -1, NULL, efbuf);
if (textvp != NULL)
export_fd_to_sb(textvp, KF_TYPE_VNODE, KF_FD_TYPE_TEXT,
- FREAD, -1, -1, 0, efbuf);
+ FREAD, -1, -1, NULL, efbuf);
if (cttyvp != NULL)
export_fd_to_sb(cttyvp, KF_TYPE_VNODE, KF_FD_TYPE_CTTY,
- FREAD | FWRITE, -1, -1, 0, efbuf);
+ FREAD | FWRITE, -1, -1, NULL, efbuf);
error = 0;
if (fdp == NULL)
goto fail;
@@ -3346,30 +3365,30 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
vref(fdp->fd_cdir);
data = fdp->fd_cdir;
export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_CWD,
- FREAD, -1, -1, 0, efbuf);
+ FREAD, -1, -1, NULL, efbuf);
}
/* root directory */
if (fdp->fd_rdir != NULL) {
vref(fdp->fd_rdir);
data = fdp->fd_rdir;
export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_ROOT,
- FREAD, -1, -1, 0, efbuf);
+ FREAD, -1, -1, NULL, efbuf);
}
/* jail directory */
if (fdp->fd_jdir != NULL) {
vref(fdp->fd_jdir);
data = fdp->fd_jdir;
export_fd_to_sb(data, KF_TYPE_VNODE, KF_FD_TYPE_JAIL,
- FREAD, -1, -1, 0, efbuf);
+ FREAD, -1, -1, NULL, efbuf);
}
for (i = 0; i < fdp->fd_nfiles; i++) {
if ((fp = fdp->fd_ofiles[i].fde_file) == NULL)
continue;
data = NULL;
#ifdef CAPABILITIES
- fd_cap_rights = cap_rights(fdp, i);
+ rights = *cap_rights(fdp, i);
#else /* !CAPABILITIES */
- fd_cap_rights = 0;
+ cap_rights_init(&rights);
#endif
switch (fp->f_type) {
case DTYPE_VNODE:
@@ -3443,8 +3462,8 @@ kern_proc_filedesc_out(struct proc *p, struct sbuf *sb, ssize_t maxlen)
* the loop continues.
*/
error = export_fd_to_sb(data, type, i, fflags, refcnt,
- offset, fd_cap_rights, efbuf);
- if (error)
+ offset, &rights, efbuf);
+ if (error != 0)
break;
}
FILEDESC_SUNLOCK(fdp);
diff --git a/sys/kern/kern_event.c b/sys/kern/kern_event.c
index dfd1c46..8bde25a 100644
--- a/sys/kern/kern_event.c
+++ b/sys/kern/kern_event.c
@@ -824,9 +824,11 @@ kern_kevent(struct thread *td, int fd, int nchanges, int nevents,
struct kevent *kevp, *changes;
struct kqueue *kq;
struct file *fp;
+ cap_rights_t rights;
int i, n, nerrors, error;
- if ((error = fget(td, fd, CAP_POST_EVENT, &fp)) != 0)
+ error = fget(td, fd, cap_rights_init(&rights, CAP_POST_EVENT), &fp);
+ if (error != 0)
return (error);
if ((error = kqueue_acquire(fp, &kq)) != 0)
goto done_norel;
@@ -964,6 +966,7 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
struct filterops *fops;
struct file *fp;
struct knote *kn, *tkn;
+ cap_rights_t rights;
int error, filt, event;
int haskqglobal;
@@ -982,7 +985,8 @@ kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *td, int wa
findkn:
if (fops->f_isfd) {
KASSERT(td != NULL, ("td is NULL"));
- error = fget(td, kev->ident, CAP_POLL_EVENT, &fp);
+ error = fget(td, kev->ident,
+ cap_rights_init(&rights, CAP_POLL_EVENT), &fp);
if (error)
goto done;
@@ -2237,9 +2241,11 @@ kqfd_register(int fd, struct kevent *kev, struct thread *td, int waitok)
{
struct kqueue *kq;
struct file *fp;
+ cap_rights_t rights;
int error;
- if ((error = fget(td, fd, CAP_POST_EVENT, &fp)) != 0)
+ error = fget(td, fd, cap_rights_init(&rights, CAP_POST_EVENT), &fp);
+ if (error != 0)
return (error);
if ((error = kqueue_acquire(fp, &kq)) != 0)
goto noacquire;
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 833fd18..45f732b 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -338,6 +338,7 @@ do_execve(td, args, mac_p)
struct ucred *tracecred = NULL;
#endif
struct vnode *textvp = NULL, *binvp = NULL;
+ cap_rights_t rights;
int credential_changing;
int textset;
#ifdef MAC
@@ -438,7 +439,8 @@ interpret:
/*
* Descriptors opened only with O_EXEC or O_RDONLY are allowed.
*/
- error = fgetvp_exec(td, args->fd, CAP_FEXECVE, &binvp);
+ error = fgetvp_exec(td, args->fd,
+ cap_rights_init(&rights, CAP_FEXECVE), &binvp);
if (error)
goto exec_fail;
vn_lock(binvp, LK_EXCLUSIVE | LK_RETRY);
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index e512a33..3b34fb0 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -779,8 +779,8 @@ ktrstruct(name, data, datalen)
void
ktrcapfail(type, needed, held)
enum ktr_cap_fail_type type;
- cap_rights_t needed;
- cap_rights_t held;
+ const cap_rights_t *needed;
+ const cap_rights_t *held;
{
struct thread *td = curthread;
struct ktr_request *req;
@@ -791,8 +791,8 @@ ktrcapfail(type, needed, held)
return;
kcf = &req->ktr_data.ktr_cap_fail;
kcf->cap_type = type;
- kcf->cap_needed = needed;
- kcf->cap_held = held;
+ kcf->cap_needed = *needed;
+ kcf->cap_held = *held;
ktr_enqueuerequest(td, req);
ktrace_exit(td);
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 22fc1b7..1797ebc 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1726,6 +1726,7 @@ sys_pdkill(td, uap)
{
#ifdef PROCDESC
struct proc *p;
+ cap_rights_t rights;
int error;
AUDIT_ARG_SIGNUM(uap->signum);
@@ -1733,7 +1734,8 @@ sys_pdkill(td, uap)
if ((u_int)uap->signum > _SIG_MAXSIG)
return (EINVAL);
- error = procdesc_find(td, uap->fd, CAP_PDKILL, &p);
+ error = procdesc_find(td, uap->fd,
+ cap_rights_init(&rights, CAP_PDKILL), &p);
if (error)
return (error);
AUDIT_ARG_PROCESS(p);
diff --git a/sys/kern/subr_capability.c b/sys/kern/subr_capability.c
new file mode 100644
index 0000000..7043fe7
--- /dev/null
+++ b/sys/kern/subr_capability.c
@@ -0,0 +1,285 @@
+/*-
+ * Copyright (c) 2013 FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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$");
+
+#ifdef _KERNEL
+#include <sys/types.h>
+#include <sys/capability.h>
+#include <sys/systm.h>
+
+#include <machine/stdarg.h>
+#else /* !_KERNEL */
+#include <sys/types.h>
+#include <sys/capability.h>
+
+#include <assert.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#endif
+
+#ifdef _KERNEL
+#define assert(exp) KASSERT((exp), ("%s:%u", __func__, __LINE__))
+#endif
+
+static __inline unsigned int
+right_to_index(uint64_t right)
+{
+ static const int bit2idx[] = {
+ -1, 0, 1, -1, 2, -1, -1, -1, 3, -1, -1, -1, -1, -1, -1, -1,
+ 4, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ int idx;
+
+ idx = CAPIDXBIT(right);
+ assert(idx == 1 || idx == 2 || idx == 4 || idx == 8 || idx == 16);
+
+ idx = bit2idx[idx];
+ assert(idx >= 0 && idx <= 4);
+
+ return ((unsigned int)idx);
+}
+
+static void
+cap_rights_vset(cap_rights_t *rights, va_list ap)
+{
+ unsigned int i, n;
+ uint64_t right;
+
+ assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
+
+ n = CAPARSIZE(rights);
+
+ for (;;) {
+ right = (uint64_t)va_arg(ap, unsigned long long);
+ if (right == 0)
+ break;
+ assert(CAPRVER(right) == 0);
+ i = right_to_index(right);
+ assert(i < n);
+ assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
+ rights->cr_rights[i] |= right;
+ assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
+ }
+}
+
+static void
+cap_rights_vclear(cap_rights_t *rights, va_list ap)
+{
+ unsigned int i, n;
+ uint64_t right;
+
+ assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
+
+ n = CAPARSIZE(rights);
+
+ for (;;) {
+ right = (uint64_t)va_arg(ap, unsigned long long);
+ if (right == 0)
+ break;
+ assert(CAPRVER(right) == 0);
+ i = right_to_index(right);
+ assert(i < n);
+ assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
+ rights->cr_rights[i] &= ~(right & 0x01FFFFFFFFFFFFFFULL);
+ assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
+ }
+}
+
+static bool
+cap_rights_is_vset(const cap_rights_t *rights, va_list ap)
+{
+ unsigned int i, n;
+ uint64_t right;
+
+ assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
+
+ n = CAPARSIZE(rights);
+
+ for (;;) {
+ right = (uint64_t)va_arg(ap, unsigned long long);
+ if (right == 0)
+ break;
+ assert(CAPRVER(right) == 0);
+ i = right_to_index(right);
+ assert(i < n);
+ assert(CAPIDXBIT(rights->cr_rights[i]) == CAPIDXBIT(right));
+ if ((rights->cr_rights[i] & right) != right)
+ return (false);
+ }
+
+ return (true);
+}
+
+cap_rights_t *
+__cap_rights_init(int version, cap_rights_t *rights, ...)
+{
+ unsigned int n;
+ va_list ap;
+
+ assert(version == CAP_RIGHTS_VERSION_00);
+
+ n = version + 2;
+ memset(rights->cr_rights, 0, sizeof(rights->cr_rights[0]) * n);
+ CAP_NONE(rights);
+ va_start(ap, rights);
+ cap_rights_vset(rights, ap);
+ va_end(ap);
+
+ return (rights);
+}
+
+void
+__cap_rights_set(cap_rights_t *rights, ...)
+{
+ va_list ap;
+
+ assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
+
+ va_start(ap, rights);
+ cap_rights_vset(rights, ap);
+ va_end(ap);
+}
+
+void
+__cap_rights_clear(cap_rights_t *rights, ...)
+{
+ va_list ap;
+
+ assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
+
+ va_start(ap, rights);
+ cap_rights_vclear(rights, ap);
+ va_end(ap);
+}
+
+bool
+__cap_rights_is_set(const cap_rights_t *rights, ...)
+{
+ va_list ap;
+ bool ret;
+
+ assert(CAPVER(rights) == CAP_RIGHTS_VERSION_00);
+
+ va_start(ap, rights);
+ ret = cap_rights_is_vset(rights, ap);
+ va_end(ap);
+
+ return (ret);
+}
+
+bool
+cap_rights_is_valid(const cap_rights_t *rights)
+{
+ cap_rights_t allrights;
+ unsigned int i, j;
+
+ if (CAPVER(rights) != CAP_RIGHTS_VERSION_00)
+ return (false);
+ CAP_ALL(&allrights);
+ if (!cap_rights_contains(&allrights, rights))
+ return (false);
+ for (i = 0; i < CAPARSIZE(rights); i++) {
+ j = right_to_index(rights->cr_rights[i]);
+ if (i != j)
+ return (false);
+ if (i > 0) {
+ if (CAPRVER(rights->cr_rights[i]) != 0)
+ return (false);
+ }
+ }
+
+ return (true);
+}
+
+void
+cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src)
+{
+ unsigned int i, n;
+
+ assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00);
+ assert(CAPVER(src) == CAP_RIGHTS_VERSION_00);
+ assert(CAPVER(dst) == CAPVER(src));
+ assert(cap_rights_is_valid(src));
+ assert(cap_rights_is_valid(dst));
+
+ n = CAPARSIZE(dst);
+
+ for (i = 0; i < n; i++)
+ dst->cr_rights[i] |= src->cr_rights[i];
+
+ assert(cap_rights_is_valid(src));
+ assert(cap_rights_is_valid(dst));
+}
+
+void
+cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src)
+{
+ unsigned int i, n;
+
+ assert(CAPVER(dst) == CAP_RIGHTS_VERSION_00);
+ assert(CAPVER(src) == CAP_RIGHTS_VERSION_00);
+ assert(CAPVER(dst) == CAPVER(src));
+ assert(cap_rights_is_valid(src));
+ assert(cap_rights_is_valid(dst));
+
+ n = CAPARSIZE(dst);
+
+ for (i = 0; i < n; i++) {
+ dst->cr_rights[i] &=
+ ~(src->cr_rights[i] & 0x01FFFFFFFFFFFFFFULL);
+ }
+
+ assert(cap_rights_is_valid(src));
+ assert(cap_rights_is_valid(dst));
+}
+
+bool
+cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little)
+{
+ unsigned int i, n;
+
+ assert(CAPVER(big) == CAP_RIGHTS_VERSION_00);
+ assert(CAPVER(little) == CAP_RIGHTS_VERSION_00);
+ assert(CAPVER(big) == CAPVER(little));
+
+ n = CAPARSIZE(big);
+
+ for (i = 0; i < n; i++) {
+ if ((big->cr_rights[i] & little->cr_rights[i]) !=
+ little->cr_rights[i]) {
+ return (false);
+ }
+ }
+
+ return (true);
+}
diff --git a/sys/kern/sys_capability.c b/sys/kern/sys_capability.c
index 224042e..456f7ac 100644
--- a/sys/kern/sys_capability.c
+++ b/sys/kern/sys_capability.c
@@ -148,16 +148,19 @@ FEATURE(security_capabilities, "Capsicum Capabilities");
MALLOC_DECLARE(M_FILECAPS);
static inline int
-_cap_check(cap_rights_t have, cap_rights_t need, enum ktr_cap_fail_type type)
+_cap_check(const cap_rights_t *havep, const cap_rights_t *needp,
+ enum ktr_cap_fail_type type)
{
+ int i;
-
- if ((need & ~have) != 0) {
+ for (i = 0; i < nitems(havep->cr_rights); i++) {
+ if (!cap_rights_contains(havep, needp)) {
#ifdef KTRACE
- if (KTRPOINT(curthread, KTR_CAPFAIL))
- ktrcapfail(type, need, have);
+ if (KTRPOINT(curthread, KTR_CAPFAIL))
+ ktrcapfail(type, needp, havep);
#endif
- return (ENOTCAPABLE);
+ return (ENOTCAPABLE);
+ }
}
return (0);
}
@@ -166,26 +169,26 @@ _cap_check(cap_rights_t have, cap_rights_t need, enum ktr_cap_fail_type type)
* Test whether a capability grants the requested rights.
*/
int
-cap_check(cap_rights_t have, cap_rights_t need)
+cap_check(const cap_rights_t *havep, const cap_rights_t *needp)
{
- return (_cap_check(have, need, CAPFAIL_NOTCAPABLE));
+ return (_cap_check(havep, needp, CAPFAIL_NOTCAPABLE));
}
/*
* Convert capability rights into VM access flags.
*/
u_char
-cap_rights_to_vmprot(cap_rights_t have)
+cap_rights_to_vmprot(cap_rights_t *havep)
{
u_char maxprot;
maxprot = VM_PROT_NONE;
- if (have & CAP_MMAP_R)
+ if (cap_rights_is_set(havep, CAP_MMAP_R))
maxprot |= VM_PROT_READ;
- if (have & CAP_MMAP_W)
+ if (cap_rights_is_set(havep, CAP_MMAP_W))
maxprot |= VM_PROT_WRITE;
- if (have & CAP_MMAP_X)
+ if (cap_rights_is_set(havep, CAP_MMAP_X))
maxprot |= VM_PROT_EXECUTE;
return (maxprot);
@@ -196,11 +199,11 @@ cap_rights_to_vmprot(cap_rights_t have)
* any other way, as we want to keep all capability permission evaluation in
* this one file.
*/
-cap_rights_t
+cap_rights_t *
cap_rights(struct filedesc *fdp, int fd)
{
- return (fdp->fd_ofiles[fd].fde_rights);
+ return (&fdp->fd_ofiles[fd].fde_rights);
}
/*
@@ -211,32 +214,57 @@ sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
{
struct filedesc *fdp;
cap_rights_t rights;
- int error, fd;
+ int error, fd, version;
- fd = uap->fd;
- rights = uap->rights;
+ cap_rights_init(&rights);
- AUDIT_ARG_FD(fd);
- AUDIT_ARG_RIGHTS(rights);
+ error = copyin(uap->rightsp, &rights, sizeof(rights.cr_rights[0]));
+ if (error != 0)
+ return (error);
+ version = CAPVER(&rights);
+ if (version != CAP_RIGHTS_VERSION_00)
+ return (EINVAL);
- if ((rights & ~CAP_ALL) != 0)
+ error = copyin(uap->rightsp, &rights,
+ sizeof(rights.cr_rights[0]) * CAPARSIZE(&rights));
+ if (error != 0)
+ return (error);
+ /* Check for race. */
+ if (CAPVER(&rights) != version)
return (EINVAL);
+ if (!cap_rights_is_valid(&rights))
+ return (EINVAL);
+
+ if (version != CAP_RIGHTS_VERSION) {
+ rights.cr_rights[0] &= ~(0x3ULL << 62);
+ rights.cr_rights[0] |= ((uint64_t)CAP_RIGHTS_VERSION << 62);
+ }
+#ifdef KTRACE
+ if (KTRPOINT(td, KTR_STRUCT))
+ ktrcaprights(&rights);
+#endif
+
+ fd = uap->fd;
+
+ AUDIT_ARG_FD(fd);
+ AUDIT_ARG_RIGHTS(&rights);
+
fdp = td->td_proc->p_fd;
FILEDESC_XLOCK(fdp);
if (fget_locked(fdp, fd) == NULL) {
FILEDESC_XUNLOCK(fdp);
return (EBADF);
}
- error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
+ error = _cap_check(cap_rights(fdp, fd), &rights, CAPFAIL_INCREASE);
if (error == 0) {
fdp->fd_ofiles[fd].fde_rights = rights;
- if ((rights & CAP_IOCTL) == 0) {
+ if (!cap_rights_is_set(&rights, CAP_IOCTL)) {
free(fdp->fd_ofiles[fd].fde_ioctls, M_FILECAPS);
fdp->fd_ofiles[fd].fde_ioctls = NULL;
fdp->fd_ofiles[fd].fde_nioctls = 0;
}
- if ((rights & CAP_FCNTL) == 0)
+ if (!cap_rights_is_set(&rights, CAP_FCNTL))
fdp->fd_ofiles[fd].fde_fcntls = 0;
}
FILEDESC_XUNLOCK(fdp);
@@ -247,11 +275,14 @@ sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
* System call to query the rights mask associated with a capability.
*/
int
-sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap)
+sys___cap_rights_get(struct thread *td, struct __cap_rights_get_args *uap)
{
struct filedesc *fdp;
cap_rights_t rights;
- int fd;
+ int error, fd, i, n;
+
+ if (uap->version != CAP_RIGHTS_VERSION_00)
+ return (EINVAL);
fd = uap->fd;
@@ -263,9 +294,26 @@ sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap)
FILEDESC_SUNLOCK(fdp);
return (EBADF);
}
- rights = cap_rights(fdp, fd);
+ rights = *cap_rights(fdp, fd);
FILEDESC_SUNLOCK(fdp);
- return (copyout(&rights, uap->rightsp, sizeof(*uap->rightsp)));
+ n = uap->version + 2;
+ if (uap->version != CAPVER(&rights)) {
+ /*
+ * For older versions we need to check if the descriptor
+ * doesn't contain rights not understood by the caller.
+ * If it does, we have to return an error.
+ */
+ for (i = n; i < CAPARSIZE(&rights); i++) {
+ if ((rights.cr_rights[i] & ~(0x7FULL << 57)) != 0)
+ return (EINVAL);
+ }
+ }
+ error = copyout(&rights, uap->rightsp, sizeof(rights.cr_rights[0]) * n);
+#ifdef KTRACE
+ if (error == 0 && KTRPOINT(td, KTR_STRUCT))
+ ktrcaprights(&rights);
+#endif
+ return (error);
}
/*
@@ -513,65 +561,6 @@ sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
return (copyout(&rights, uap->fcntlrightsp, sizeof(rights)));
}
-/*
- * For backward compatibility.
- */
-int
-sys_cap_new(struct thread *td, struct cap_new_args *uap)
-{
- struct filedesc *fdp;
- cap_rights_t rights;
- register_t newfd;
- int error, fd;
-
- fd = uap->fd;
- rights = uap->rights;
-
- AUDIT_ARG_FD(fd);
- AUDIT_ARG_RIGHTS(rights);
-
- if ((rights & ~CAP_ALL) != 0)
- return (EINVAL);
-
- fdp = td->td_proc->p_fd;
- FILEDESC_SLOCK(fdp);
- if (fget_locked(fdp, fd) == NULL) {
- FILEDESC_SUNLOCK(fdp);
- return (EBADF);
- }
- error = _cap_check(cap_rights(fdp, fd), rights, CAPFAIL_INCREASE);
- FILEDESC_SUNLOCK(fdp);
- if (error != 0)
- return (error);
-
- error = do_dup(td, 0, fd, 0, &newfd);
- if (error != 0)
- return (error);
-
- FILEDESC_XLOCK(fdp);
- /*
- * We don't really care about the race between checking capability
- * rights for the source descriptor and now. If capability rights
- * were ok at that earlier point, the process had this descriptor
- * with those rights, so we don't increase them in security sense,
- * the process might have done the cap_new(2) a bit earlier to get
- * the same effect.
- */
- fdp->fd_ofiles[newfd].fde_rights = rights;
- if ((rights & CAP_IOCTL) == 0) {
- free(fdp->fd_ofiles[newfd].fde_ioctls, M_FILECAPS);
- fdp->fd_ofiles[newfd].fde_ioctls = NULL;
- fdp->fd_ofiles[newfd].fde_nioctls = 0;
- }
- if ((rights & CAP_FCNTL) == 0)
- fdp->fd_ofiles[newfd].fde_fcntls = 0;
- FILEDESC_XUNLOCK(fdp);
-
- td->td_retval[0] = newfd;
-
- return (0);
-}
-
#else /* !CAPABILITIES */
/*
@@ -587,7 +576,7 @@ sys_cap_rights_limit(struct thread *td, struct cap_rights_limit_args *uap)
}
int
-sys_cap_rights_get(struct thread *td, struct cap_rights_get_args *uap)
+sys___cap_rights_get(struct thread *td, struct cap___rights_get_args *uap)
{
return (ENOSYS);
@@ -621,11 +610,4 @@ sys_cap_fcntls_get(struct thread *td, struct cap_fcntls_get_args *uap)
return (ENOSYS);
}
-int
-sys_cap_new(struct thread *td, struct cap_new_args *uap)
-{
-
- return (ENOSYS);
-}
-
#endif /* CAPABILITIES */
diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c
index 44d1a89..5eaa695 100644
--- a/sys/kern/sys_generic.c
+++ b/sys/kern/sys_generic.c
@@ -243,9 +243,10 @@ int
kern_readv(struct thread *td, int fd, struct uio *auio)
{
struct file *fp;
+ cap_rights_t rights;
int error;
- error = fget_read(td, fd, CAP_READ, &fp);
+ error = fget_read(td, fd, cap_rights_init(&rights, CAP_READ), &fp);
if (error)
return (error);
error = dofileread(td, fd, fp, auio, (off_t)-1, 0);
@@ -286,9 +287,10 @@ kern_preadv(td, fd, auio, offset)
off_t offset;
{
struct file *fp;
+ cap_rights_t rights;
int error;
- error = fget_read(td, fd, CAP_PREAD, &fp);
+ error = fget_read(td, fd, cap_rights_init(&rights, CAP_PREAD), &fp);
if (error)
return (error);
if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
@@ -452,9 +454,10 @@ int
kern_writev(struct thread *td, int fd, struct uio *auio)
{
struct file *fp;
+ cap_rights_t rights;
int error;
- error = fget_write(td, fd, CAP_WRITE, &fp);
+ error = fget_write(td, fd, cap_rights_init(&rights, CAP_WRITE), &fp);
if (error)
return (error);
error = dofilewrite(td, fd, fp, auio, (off_t)-1, 0);
@@ -495,9 +498,10 @@ kern_pwritev(td, fd, auio, offset)
off_t offset;
{
struct file *fp;
+ cap_rights_t rights;
int error;
- error = fget_write(td, fd, CAP_PWRITE, &fp);
+ error = fget_write(td, fd, cap_rights_init(&rights, CAP_PWRITE), &fp);
if (error)
return (error);
if (!(fp->f_ops->fo_flags & DFLAG_SEEKABLE))
@@ -575,12 +579,13 @@ kern_ftruncate(td, fd, length)
off_t length;
{
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(fd);
if (length < 0)
return (EINVAL);
- error = fget(td, fd, CAP_FTRUNCATE, &fp);
+ error = fget(td, fd, cap_rights_init(&rights, CAP_FTRUNCATE), &fp);
if (error)
return (error);
AUDIT_ARG_FILE(td->td_proc, fp);
@@ -705,6 +710,9 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
{
struct file *fp;
struct filedesc *fdp;
+#ifndef CAPABILITIES
+ cap_rights_t rights;
+#endif
int error, tmp, locked;
AUDIT_ARG_FD(fd);
@@ -743,7 +751,8 @@ kern_ioctl(struct thread *td, int fd, u_long com, caddr_t data)
locked = LA_UNLOCKED;
}
#else
- if ((error = fget(td, fd, CAP_IOCTL, &fp)) != 0) {
+ error = fget(td, fd, cap_rights_init(&rights, CAP_IOCTL), &fp);
+ if (error != 0) {
fp = NULL;
goto out;
}
@@ -1180,8 +1189,10 @@ selsetbits(fd_mask **ibits, fd_mask **obits, int idx, fd_mask bit, int events)
static __inline int
getselfd_cap(struct filedesc *fdp, int fd, struct file **fpp)
{
+ cap_rights_t rights;
- return (fget_unlocked(fdp, fd, CAP_POLL_EVENT, 0, fpp, NULL));
+ return (fget_unlocked(fdp, fd, cap_rights_init(&rights, CAP_POLL_EVENT),
+ 0, fpp, NULL));
}
/*
@@ -1357,6 +1368,7 @@ pollrescan(struct thread *td)
struct filedesc *fdp;
struct file *fp;
struct pollfd *fd;
+ cap_rights_t rights;
int n;
n = 0;
@@ -1373,7 +1385,8 @@ pollrescan(struct thread *td)
fp = fdp->fd_ofiles[fd->fd].fde_file;
#ifdef CAPABILITIES
if (fp == NULL ||
- cap_check(cap_rights(fdp, fd->fd), CAP_POLL_EVENT) != 0)
+ cap_check(cap_rights(fdp, fd->fd),
+ cap_rights_init(&rights, CAP_POLL_EVENT)) != 0)
#else
if (fp == NULL)
#endif
@@ -1431,6 +1444,7 @@ pollscan(td, fds, nfd)
{
struct filedesc *fdp = td->td_proc->p_fd;
struct file *fp;
+ cap_rights_t rights;
int i, n = 0;
FILEDESC_SLOCK(fdp);
@@ -1445,7 +1459,7 @@ pollscan(td, fds, nfd)
#ifdef CAPABILITIES
if (fp == NULL ||
cap_check(cap_rights(fdp, fds->fd),
- CAP_POLL_EVENT) != 0)
+ cap_rights_init(&rights, CAP_POLL_EVENT)) != 0)
#else
if (fp == NULL)
#endif
diff --git a/sys/kern/sys_procdesc.c b/sys/kern/sys_procdesc.c
index bacaf18..4bafeab 100644
--- a/sys/kern/sys_procdesc.c
+++ b/sys/kern/sys_procdesc.c
@@ -138,14 +138,14 @@ SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, procdesc_init, NULL);
* died.
*/
int
-procdesc_find(struct thread *td, int fd, cap_rights_t rights,
+procdesc_find(struct thread *td, int fd, cap_rights_t *rightsp,
struct proc **p)
{
struct procdesc *pd;
struct file *fp;
int error;
- error = fget(td, fd, rights, &fp);
+ error = fget(td, fd, rightsp, &fp);
if (error)
return (error);
if (fp->f_type != DTYPE_PROCDESC) {
@@ -185,12 +185,12 @@ procdesc_pid(struct file *fp_procdesc)
* Retrieve the PID associated with a process descriptor.
*/
int
-kern_pdgetpid(struct thread *td, int fd, cap_rights_t rights, pid_t *pidp)
+kern_pdgetpid(struct thread *td, int fd, cap_rights_t *rightsp, pid_t *pidp)
{
struct file *fp;
int error;
- error = fget(td, fd, rights, &fp);
+ error = fget(td, fd, rightsp, &fp);
if (error)
return (error);
if (fp->f_type != DTYPE_PROCDESC) {
@@ -209,11 +209,13 @@ out:
int
sys_pdgetpid(struct thread *td, struct pdgetpid_args *uap)
{
+ cap_rights_t rights;
pid_t pid;
int error;
AUDIT_ARG_FD(uap->fd);
- error = kern_pdgetpid(td, uap->fd, CAP_PDGETPID, &pid);
+ error = kern_pdgetpid(td, uap->fd,
+ cap_rights_init(&rights, CAP_PDGETPID), &pid);
if (error == 0)
error = copyout(&pid, uap->pidp, sizeof(pid));
return (error);
diff --git a/sys/kern/syscalls.master b/sys/kern/syscalls.master
index 789f95a5..e19e310 100644
--- a/sys/kern/syscalls.master
+++ b/sys/kern/syscalls.master
@@ -917,9 +917,9 @@
512 AUE_SHMCTL NOSTD { int shmctl(int shmid, int cmd, \
struct shmid_ds *buf); }
513 AUE_LPATHCONF STD { int lpathconf(char *path, int name); }
-514 AUE_CAP_NEW STD { int cap_new(int fd, uint64_t rights); }
-515 AUE_CAP_RIGHTS_GET STD { int cap_rights_get(int fd, \
- uint64_t *rightsp); }
+514 AUE_NULL OBSOL cap_new
+515 AUE_CAP_RIGHTS_GET STD { int __cap_rights_get(int version, \
+ int fd, cap_rights_t *rightsp); }
516 AUE_CAP_ENTER STD { int cap_enter(void); }
517 AUE_CAP_GETMODE STD { int cap_getmode(u_int *modep); }
518 AUE_PDFORK STD { int pdfork(int *fdp, int flags); }
@@ -957,7 +957,7 @@
struct __wrusage *wrusage, \
siginfo_t *info); }
533 AUE_CAP_RIGHTS_LIMIT STD { int cap_rights_limit(int fd, \
- uint64_t rights); }
+ cap_rights_t *rightsp); }
534 AUE_CAP_IOCTLS_LIMIT STD { int cap_ioctls_limit(int fd, \
const u_long *cmds, size_t ncmds); }
535 AUE_CAP_IOCTLS_GET STD { ssize_t cap_ioctls_get(int fd, \
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 02eccd7..4fce607 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -1837,11 +1837,13 @@ ttyhook_register(struct tty **rtp, struct proc *p, int fd,
struct cdev *dev;
struct cdevsw *cdp;
struct filedesc *fdp;
+ cap_rights_t rights;
int error, ref;
/* Validate the file descriptor. */
fdp = p->p_fd;
- error = fget_unlocked(fdp, fd, CAP_TTYHOOK, 0, &fp, NULL);
+ error = fget_unlocked(fdp, fd, cap_rights_init(&rights, CAP_TTYHOOK),
+ 0, &fp, NULL);
if (error != 0)
return (error);
if (fp->f_ops == &badfileops) {
diff --git a/sys/kern/uipc_mqueue.c b/sys/kern/uipc_mqueue.c
index 62c54d3..6a1bf76 100644
--- a/sys/kern/uipc_mqueue.c
+++ b/sys/kern/uipc_mqueue.c
@@ -2086,19 +2086,19 @@ sys_kmq_unlink(struct thread *td, struct kmq_unlink_args *uap)
return (error);
}
-typedef int (*_fgetf)(struct thread *, int, cap_rights_t, struct file **);
+typedef int (*_fgetf)(struct thread *, int, cap_rights_t *, struct file **);
/*
* Get message queue by giving file slot
*/
static int
-_getmq(struct thread *td, int fd, cap_rights_t rights, _fgetf func,
+_getmq(struct thread *td, int fd, cap_rights_t *rightsp, _fgetf func,
struct file **fpp, struct mqfs_node **ppn, struct mqueue **pmq)
{
struct mqfs_node *pn;
int error;
- error = func(td, fd, rights, fpp);
+ error = func(td, fd, rightsp, fpp);
if (error)
return (error);
if (&mqueueops != (*fpp)->f_ops) {
@@ -2117,21 +2117,30 @@ static __inline int
getmq(struct thread *td, int fd, struct file **fpp, struct mqfs_node **ppn,
struct mqueue **pmq)
{
- return _getmq(td, fd, CAP_POLL_EVENT, fget, fpp, ppn, pmq);
+ cap_rights_t rights;
+
+ return _getmq(td, fd, cap_rights_init(&rights, CAP_POLL_EVENT), fget,
+ fpp, ppn, pmq);
}
static __inline int
getmq_read(struct thread *td, int fd, struct file **fpp,
struct mqfs_node **ppn, struct mqueue **pmq)
{
- return _getmq(td, fd, CAP_READ, fget_read, fpp, ppn, pmq);
+ cap_rights_t rights;
+
+ return _getmq(td, fd, cap_rights_init(&rights, CAP_READ), fget_read,
+ fpp, ppn, pmq);
}
static __inline int
getmq_write(struct thread *td, int fd, struct file **fpp,
struct mqfs_node **ppn, struct mqueue **pmq)
{
- return _getmq(td, fd, CAP_WRITE, fget_write, fpp, ppn, pmq);
+ cap_rights_t rights;
+
+ return _getmq(td, fd, cap_rights_init(&rights, CAP_WRITE), fget_write,
+ fpp, ppn, pmq);
}
static int
@@ -2238,6 +2247,7 @@ sys_kmq_timedsend(struct thread *td, struct kmq_timedsend_args *uap)
static int
kern_kmq_notify(struct thread *td, int mqd, struct sigevent *sigev)
{
+ cap_rights_t rights;
struct filedesc *fdp;
struct proc *p;
struct mqueue *mq;
@@ -2269,7 +2279,8 @@ again:
goto out;
}
#ifdef CAPABILITIES
- error = cap_check(cap_rights(fdp, mqd), CAP_POLL_EVENT);
+ error = cap_check(cap_rights(fdp, mqd),
+ cap_rights_init(&rights, CAP_POLL_EVENT));
if (error) {
FILEDESC_SUNLOCK(fdp);
goto out;
diff --git a/sys/kern/uipc_sem.c b/sys/kern/uipc_sem.c
index 8c86cc4..f641654 100644
--- a/sys/kern/uipc_sem.c
+++ b/sys/kern/uipc_sem.c
@@ -116,7 +116,7 @@ static int ksem_create(struct thread *td, const char *path,
semid_t *semidp, mode_t mode, unsigned int value,
int flags, int compat32);
static void ksem_drop(struct ksem *ks);
-static int ksem_get(struct thread *td, semid_t id, cap_rights_t rights,
+static int ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp,
struct file **fpp);
static struct ksem *ksem_hold(struct ksem *ks);
static void ksem_insert(char *path, Fnv32_t fnv, struct ksem *ks);
@@ -600,13 +600,14 @@ ksem_create(struct thread *td, const char *name, semid_t *semidp, mode_t mode,
}
static int
-ksem_get(struct thread *td, semid_t id, cap_rights_t rights, struct file **fpp)
+ksem_get(struct thread *td, semid_t id, cap_rights_t *rightsp,
+ struct file **fpp)
{
struct ksem *ks;
struct file *fp;
int error;
- error = fget(td, id, rights, &fp);
+ error = fget(td, id, rightsp, &fp);
if (error)
return (EINVAL);
if (fp->f_type != DTYPE_SEM) {
@@ -720,11 +721,13 @@ struct ksem_post_args {
int
sys_ksem_post(struct thread *td, struct ksem_post_args *uap)
{
+ cap_rights_t rights;
struct file *fp;
struct ksem *ks;
int error;
- error = ksem_get(td, uap->id, CAP_SEM_POST, &fp);
+ error = ksem_get(td, uap->id,
+ cap_rights_init(&rights, CAP_SEM_POST), &fp);
if (error)
return (error);
ks = fp->f_data;
@@ -809,12 +812,13 @@ kern_sem_wait(struct thread *td, semid_t id, int tryflag,
{
struct timespec ts1, ts2;
struct timeval tv;
+ cap_rights_t rights;
struct file *fp;
struct ksem *ks;
int error;
DP((">>> kern_sem_wait entered! pid=%d\n", (int)td->td_proc->p_pid));
- error = ksem_get(td, id, CAP_SEM_WAIT, &fp);
+ error = ksem_get(td, id, cap_rights_init(&rights, CAP_SEM_WAIT), &fp);
if (error)
return (error);
ks = fp->f_data;
@@ -876,11 +880,13 @@ struct ksem_getvalue_args {
int
sys_ksem_getvalue(struct thread *td, struct ksem_getvalue_args *uap)
{
+ cap_rights_t rights;
struct file *fp;
struct ksem *ks;
int error, val;
- error = ksem_get(td, uap->id, CAP_SEM_GETVALUE, &fp);
+ error = ksem_get(td, uap->id,
+ cap_rights_init(&rights, CAP_SEM_GETVALUE), &fp);
if (error)
return (error);
ks = fp->f_data;
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 72663a2..7e25da8 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -164,13 +164,13 @@ SYSCTL_PROC(_kern_ipc, OID_AUTO, sfstat, CTLTYPE_OPAQUE | CTLFLAG_RW,
* A reference on the file entry is held upon returning.
*/
static int
-getsock_cap(struct filedesc *fdp, int fd, cap_rights_t rights,
+getsock_cap(struct filedesc *fdp, int fd, cap_rights_t *rightsp,
struct file **fpp, u_int *fflagp)
{
struct file *fp;
int error;
- error = fget_unlocked(fdp, fd, rights, 0, &fp, NULL);
+ error = fget_unlocked(fdp, fd, rightsp, 0, &fp, NULL);
if (error != 0)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
@@ -267,11 +267,13 @@ kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
{
struct socket *so;
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(fd);
AUDIT_ARG_SOCKADDR(td, dirfd, sa);
- error = getsock_cap(td->td_proc->p_fd, fd, CAP_BIND, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_BIND), &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -334,10 +336,12 @@ sys_listen(td, uap)
{
struct socket *so;
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->s);
- error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_LISTEN, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->s,
+ cap_rights_init(&rights, CAP_LISTEN), &fp, NULL);
if (error == 0) {
so = fp->f_data;
#ifdef MAC
@@ -419,6 +423,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name,
int error;
struct socket *head, *so;
int fd;
+ cap_rights_t rights;
u_int fflag;
pid_t pgid;
int tmp;
@@ -428,7 +433,8 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name,
AUDIT_ARG_FD(s);
fdp = td->td_proc->p_fd;
- error = getsock_cap(fdp, s, CAP_ACCEPT, &headfp, &fflag);
+ error = getsock_cap(fdp, s, cap_rights_init(&rights, CAP_ACCEPT),
+ &headfp, &fflag);
if (error)
return (error);
head = headfp->f_data;
@@ -629,12 +635,14 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
{
struct socket *so;
struct file *fp;
+ cap_rights_t rights;
int error;
int interrupted = 0;
AUDIT_ARG_FD(fd);
AUDIT_ARG_SOCKADDR(td, dirfd, sa);
- error = getsock_cap(td->td_proc->p_fd, fd, CAP_CONNECT, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_CONNECT), &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -898,12 +906,12 @@ kern_sendit(td, s, mp, flags, control, segflg)
#endif
AUDIT_ARG_FD(s);
- rights = CAP_SEND;
+ cap_rights_init(&rights, CAP_SEND);
if (mp->msg_name != NULL) {
AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
- rights |= CAP_CONNECT;
+ cap_rights_set(&rights, CAP_CONNECT);
}
- error = getsock_cap(td->td_proc->p_fd, s, rights, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, s, &rights, &fp, NULL);
if (error)
return (error);
so = (struct socket *)fp->f_data;
@@ -1099,6 +1107,7 @@ kern_recvit(td, s, mp, fromseg, controlp)
struct file *fp;
struct socket *so;
struct sockaddr *fromsa = NULL;
+ cap_rights_t rights;
#ifdef KTRACE
struct uio *ktruio = NULL;
#endif
@@ -1107,7 +1116,8 @@ kern_recvit(td, s, mp, fromseg, controlp)
*controlp = NULL;
AUDIT_ARG_FD(s);
- error = getsock_cap(td->td_proc->p_fd, s, CAP_RECV, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, s,
+ cap_rights_init(&rights, CAP_RECV), &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -1420,11 +1430,12 @@ sys_shutdown(td, uap)
{
struct socket *so;
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->s);
- error = getsock_cap(td->td_proc->p_fd, uap->s, CAP_SHUTDOWN, &fp,
- NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->s,
+ cap_rights_init(&rights, CAP_SHUTDOWN), &fp, NULL);
if (error == 0) {
so = fp->f_data;
error = soshutdown(so, uap->how);
@@ -1464,6 +1475,7 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize)
struct socket *so;
struct file *fp;
struct sockopt sopt;
+ cap_rights_t rights;
if (val == NULL && valsize != 0)
return (EFAULT);
@@ -1487,7 +1499,8 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize)
}
AUDIT_ARG_FD(s);
- error = getsock_cap(td->td_proc->p_fd, s, CAP_SETSOCKOPT, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, s,
+ cap_rights_init(&rights, CAP_SETSOCKOPT), &fp, NULL);
if (error == 0) {
so = fp->f_data;
error = sosetopt(so, &sopt);
@@ -1543,6 +1556,7 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize)
struct socket *so;
struct file *fp;
struct sockopt sopt;
+ cap_rights_t rights;
if (val == NULL)
*valsize = 0;
@@ -1566,7 +1580,8 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize)
}
AUDIT_ARG_FD(s);
- error = getsock_cap(td->td_proc->p_fd, s, CAP_GETSOCKOPT, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, s,
+ cap_rights_init(&rights, CAP_GETSOCKOPT), &fp, NULL);
if (error == 0) {
so = fp->f_data;
error = sogetopt(so, &sopt);
@@ -1621,11 +1636,13 @@ kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
{
struct socket *so;
struct file *fp;
+ cap_rights_t rights;
socklen_t len;
int error;
AUDIT_ARG_FD(fd);
- error = getsock_cap(td->td_proc->p_fd, fd, CAP_GETSOCKNAME, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_GETSOCKNAME), &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -1718,11 +1735,13 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
{
struct socket *so;
struct file *fp;
+ cap_rights_t rights;
socklen_t len;
int error;
AUDIT_ARG_FD(fd);
- error = getsock_cap(td->td_proc->p_fd, fd, CAP_GETPEERNAME, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_GETPEERNAME), &fp, NULL);
if (error)
return (error);
so = fp->f_data;
@@ -1907,6 +1926,7 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
struct sf_hdtr hdtr;
struct uio *hdr_uio, *trl_uio;
struct file *fp;
+ cap_rights_t rights;
int error;
if (uap->offset < 0)
@@ -1937,8 +1957,10 @@ do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
* sendfile(2) can start at any offset within a file so we require
* CAP_READ+CAP_SEEK = CAP_PREAD.
*/
- if ((error = fget_read(td, uap->fd, CAP_PREAD, &fp)) != 0)
+ if ((error = fget_read(td, uap->fd,
+ cap_rights_init(&rights, CAP_PREAD), &fp)) != 0) {
goto out;
+ }
error = fo_sendfile(fp, uap->s, hdr_uio, trl_uio, uap->offset,
uap->nbytes, uap->sbytes, uap->flags, compat ? SFK_COMPAT : 0, td);
@@ -1983,6 +2005,7 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
struct sf_buf *sf;
struct vm_page *pg;
struct vattr va;
+ cap_rights_t rights;
off_t off, xfsize, fsbytes = 0, sbytes = 0, rem = 0;
int error, hdrlen = 0, mnw = 0;
int bsize;
@@ -2030,8 +2053,9 @@ vn_sendfile(struct file *fp, int sockfd, struct uio *hdr_uio,
* The socket must be a stream socket and connected.
* Remember if it a blocking or non-blocking socket.
*/
- if ((error = getsock_cap(td->td_proc->p_fd, sockfd, CAP_SEND,
- &sock_fp, NULL)) != 0)
+ error = getsock_cap(td->td_proc->p_fd, sockfd,
+ cap_rights_init(&rights, CAP_SEND), &sock_fp, NULL);
+ if (error != 0)
goto out;
so = sock_fp->f_data;
if (so->so_type != SOCK_STREAM) {
@@ -2463,10 +2487,12 @@ sys_sctp_peeloff(td, uap)
int error;
struct socket *head, *so;
int fd;
+ cap_rights_t rights;
u_int fflag;
AUDIT_ARG_FD(uap->sd);
- error = fgetsock(td, uap->sd, CAP_PEELOFF, &head, &fflag);
+ error = fgetsock(td, uap->sd, cap_rights_init(&rights, CAP_PEELOFF),
+ &head, &fflag);
if (error)
goto done2;
if (head->so_proto->pr_protocol != IPPROTO_SCTP) {
@@ -2574,18 +2600,18 @@ sys_sctp_generic_sendmsg (td, uap)
u_sinfo = &sinfo;
}
- rights = CAP_SEND;
+ cap_rights_init(&rights, CAP_SEND);
if (uap->tolen) {
error = getsockaddr(&to, uap->to, uap->tolen);
if (error) {
to = NULL;
goto sctp_bad2;
}
- rights |= CAP_CONNECT;
+ cap_rights_set(&rights, CAP_CONNECT);
}
AUDIT_ARG_FD(uap->sd);
- error = getsock_cap(td->td_proc->p_fd, uap->sd, rights, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
if (error)
goto sctp_bad;
#ifdef KTRACE
@@ -2685,18 +2711,18 @@ sys_sctp_generic_sendmsg_iov(td, uap)
return (error);
u_sinfo = &sinfo;
}
- rights = CAP_SEND;
+ cap_rights_init(&rights, CAP_SEND);
if (uap->tolen) {
error = getsockaddr(&to, uap->to, uap->tolen);
if (error) {
to = NULL;
goto sctp_bad2;
}
- rights |= CAP_CONNECT;
+ cap_rights_set(&rights, CAP_CONNECT);
}
AUDIT_ARG_FD(uap->sd);
- error = getsock_cap(td->td_proc->p_fd, uap->sd, rights, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd, &rights, &fp, NULL);
if (error)
goto sctp_bad1;
@@ -2804,12 +2830,14 @@ sys_sctp_generic_recvmsg(td, uap)
ssize_t len;
int i, msg_flags;
int error = 0;
+ cap_rights_t rights;
#ifdef KTRACE
struct uio *ktruio = NULL;
#endif
AUDIT_ARG_FD(uap->sd);
- error = getsock_cap(td->td_proc->p_fd, uap->sd, CAP_RECV, &fp, NULL);
+ error = getsock_cap(td->td_proc->p_fd, uap->sd,
+ cap_rights_init(&rights, CAP_RECV), &fp, NULL);
if (error) {
return (error);
}
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 7a4db04..c0a5d2e 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -464,6 +464,7 @@ uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
struct unpcb *unp;
struct vnode *vp;
struct mount *mp;
+ cap_rights_t rights;
char *buf;
unp = sotounpcb(so);
@@ -502,7 +503,7 @@ uipc_bindat(int fd, struct socket *so, struct sockaddr *nam, struct thread *td)
restart:
NDINIT_ATRIGHTS(&nd, CREATE, NOFOLLOW | LOCKPARENT | SAVENAME,
- UIO_SYSSPACE, buf, fd, CAP_BINDAT, td);
+ UIO_SYSSPACE, buf, fd, cap_rights_init(&rights, CAP_BINDAT), td);
/* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
error = namei(&nd);
if (error)
@@ -1276,10 +1277,11 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam,
struct vnode *vp;
struct socket *so2, *so3;
struct unpcb *unp, *unp2, *unp3;
- int error, len;
struct nameidata nd;
char buf[SOCK_MAXADDRLEN];
struct sockaddr *sa;
+ cap_rights_t rights;
+ int error, len;
UNP_LINK_WLOCK_ASSERT();
@@ -1305,7 +1307,7 @@ unp_connectat(int fd, struct socket *so, struct sockaddr *nam,
sa = malloc(sizeof(struct sockaddr_un), M_SONAME, M_WAITOK);
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF,
- UIO_SYSSPACE, buf, fd, CAP_CONNECTAT, td);
+ UIO_SYSSPACE, buf, fd, cap_rights_init(&rights, CAP_CONNECTAT), td);
error = namei(&nd);
if (error)
vp = NULL;
diff --git a/sys/kern/vfs_acl.c b/sys/kern/vfs_acl.c
index 1c9923d..362792b 100644
--- a/sys/kern/vfs_acl.c
+++ b/sys/kern/vfs_acl.c
@@ -399,9 +399,11 @@ int
sys___acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap)
{
struct file *fp;
+ cap_rights_t rights;
int error;
- error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_GET, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->filedes,
+ cap_rights_init(&rights, CAP_ACL_GET), &fp);
if (error == 0) {
error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp);
fdrop(fp, td);
@@ -416,9 +418,11 @@ int
sys___acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap)
{
struct file *fp;
+ cap_rights_t rights;
int error;
- error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_SET, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->filedes,
+ cap_rights_init(&rights, CAP_ACL_SET), &fp);
if (error == 0) {
error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp);
fdrop(fp, td);
@@ -469,10 +473,11 @@ int
sys___acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap)
{
struct file *fp;
+ cap_rights_t rights;
int error;
- error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_DELETE,
- &fp);
+ error = getvnode(td->td_proc->p_fd, uap->filedes,
+ cap_rights_init(&rights, CAP_ACL_DELETE), &fp);
if (error == 0) {
error = vacl_delete(td, fp->f_vnode, uap->type);
fdrop(fp, td);
@@ -523,10 +528,11 @@ int
sys___acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap)
{
struct file *fp;
+ cap_rights_t rights;
int error;
- error = getvnode(td->td_proc->p_fd, uap->filedes, CAP_ACL_CHECK,
- &fp);
+ error = getvnode(td->td_proc->p_fd, uap->filedes,
+ cap_rights_init(&rights, CAP_ACL_CHECK), &fp);
if (error == 0) {
error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp);
fdrop(fp, td);
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index a66f7c2..9f3adaf 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -1567,6 +1567,7 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
int type, struct aiocb_ops *ops)
{
struct proc *p = td->td_proc;
+ cap_rights_t rights;
struct file *fp;
struct socket *so;
struct aiocblist *aiocbe, *cb;
@@ -1647,19 +1648,21 @@ aio_aqueue(struct thread *td, struct aiocb *job, struct aioliojob *lj,
fd = aiocbe->uaiocb.aio_fildes;
switch (opcode) {
case LIO_WRITE:
- error = fget_write(td, fd, CAP_PWRITE, &fp);
+ error = fget_write(td, fd,
+ cap_rights_init(&rights, CAP_PWRITE), &fp);
break;
case LIO_READ:
- error = fget_read(td, fd, CAP_PREAD, &fp);
+ error = fget_read(td, fd,
+ cap_rights_init(&rights, CAP_PREAD), &fp);
break;
case LIO_SYNC:
- error = fget(td, fd, CAP_FSYNC, &fp);
+ error = fget(td, fd, cap_rights_init(&rights, CAP_FSYNC), &fp);
break;
case LIO_MLOCK:
fp = NULL;
break;
case LIO_NOP:
- error = fget(td, fd, CAP_NONE, &fp);
+ error = fget(td, fd, cap_rights_init(&rights), &fp);
break;
default:
error = EINVAL;
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 700a70c..bc7b942 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -216,6 +216,7 @@ sys_extattr_set_fd(td, uap)
{
struct file *fp;
char attrname[EXTATTR_MAXNAMELEN];
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
@@ -225,7 +226,8 @@ sys_extattr_set_fd(td, uap)
return (error);
AUDIT_ARG_TEXT(attrname);
- error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_SET, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_EXTATTR_SET), &fp);
if (error)
return (error);
@@ -389,6 +391,7 @@ sys_extattr_get_fd(td, uap)
{
struct file *fp;
char attrname[EXTATTR_MAXNAMELEN];
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
@@ -398,7 +401,8 @@ sys_extattr_get_fd(td, uap)
return (error);
AUDIT_ARG_TEXT(attrname);
- error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_GET, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_EXTATTR_GET), &fp);
if (error)
return (error);
@@ -531,6 +535,7 @@ sys_extattr_delete_fd(td, uap)
{
struct file *fp;
char attrname[EXTATTR_MAXNAMELEN];
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
@@ -540,8 +545,8 @@ sys_extattr_delete_fd(td, uap)
return (error);
AUDIT_ARG_TEXT(attrname);
- error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_DELETE,
- &fp);
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_EXTATTR_DELETE), &fp);
if (error)
return (error);
@@ -687,11 +692,13 @@ sys_extattr_list_fd(td, uap)
} */ *uap;
{
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_VALUE(uap->attrnamespace);
- error = getvnode(td->td_proc->p_fd, uap->fd, CAP_EXTATTR_LIST, &fp);
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_EXTATTR_LIST), &fp);
if (error)
return (error);
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 7fe1908..d4d0166 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -222,20 +222,26 @@ namei(struct nameidata *ndp)
dp = ndp->ni_startdir;
error = 0;
} else if (ndp->ni_dirfd != AT_FDCWD) {
+ cap_rights_t rights;
+
+ rights = ndp->ni_rightsneeded;
+ cap_rights_set(&rights, CAP_LOOKUP);
+
if (cnp->cn_flags & AUDITVNODE1)
AUDIT_ARG_ATFD1(ndp->ni_dirfd);
if (cnp->cn_flags & AUDITVNODE2)
AUDIT_ARG_ATFD2(ndp->ni_dirfd);
error = fgetvp_rights(td, ndp->ni_dirfd,
- ndp->ni_rightsneeded | CAP_LOOKUP,
- &ndp->ni_filecaps, &dp);
+ &rights, &ndp->ni_filecaps, &dp);
#ifdef CAPABILITIES
/*
* If file descriptor doesn't have all rights,
* all lookups relative to it must also be
* strictly relative.
*/
- if (ndp->ni_filecaps.fc_rights != CAP_ALL ||
+ CAP_ALL(&rights);
+ if (!cap_rights_contains(&ndp->ni_filecaps.fc_rights,
+ &rights) ||
ndp->ni_filecaps.fc_fcntls != CAP_FCNTL_ALL ||
ndp->ni_filecaps.fc_nioctls != -1) {
ndp->ni_strictrelative = 1;
@@ -1059,6 +1065,27 @@ bad:
return (error);
}
+void
+NDINIT_ALL(struct nameidata *ndp, u_long op, u_long flags, enum uio_seg segflg,
+ const char *namep, int dirfd, struct vnode *startdir, cap_rights_t *rightsp,
+ struct thread *td)
+{
+
+ ndp->ni_cnd.cn_nameiop = op;
+ ndp->ni_cnd.cn_flags = flags;
+ ndp->ni_segflg = segflg;
+ ndp->ni_dirp = namep;
+ ndp->ni_dirfd = dirfd;
+ ndp->ni_startdir = startdir;
+ ndp->ni_strictrelative = 0;
+ if (rightsp != NULL)
+ ndp->ni_rightsneeded = *rightsp;
+ else
+ cap_rights_init(&ndp->ni_rightsneeded);
+ filecaps_init(&ndp->ni_filecaps);
+ ndp->ni_cnd.cn_thread = td;
+}
+
/*
* Free data allocated by namei(); see namei(9) for details.
*/
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 2877ad2..7df315d 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -367,10 +367,12 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
struct mount *mp;
struct statfs *sp, sb;
struct vnode *vp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(fd);
- error = getvnode(td->td_proc->p_fd, fd, CAP_FSTATFS, &fp);
+ error = getvnode(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_FSTATFS), &fp);
if (error)
return (error);
vp = fp->f_vnode;
@@ -730,10 +732,13 @@ sys_fchdir(td, uap)
struct vnode *vp, *tdp, *vpold;
struct mount *mp;
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
- if ((error = getvnode(fdp, uap->fd, CAP_FCHDIR, &fp)) != 0)
+ error = getvnode(fdp, uap->fd, cap_rights_init(&rights, CAP_FCHDIR),
+ &fp);
+ if (error != 0)
return (error);
vp = fp->f_vnode;
VREF(vp);
@@ -954,42 +959,39 @@ change_root(vp, td)
return (0);
}
-static __inline cap_rights_t
-flags_to_rights(int flags)
+static __inline void
+flags_to_rights(int flags, cap_rights_t *rightsp)
{
- cap_rights_t rights = 0;
if (flags & O_EXEC) {
- rights |= CAP_FEXECVE;
+ cap_rights_set(rightsp, CAP_FEXECVE);
} else {
switch ((flags & O_ACCMODE)) {
case O_RDONLY:
- rights |= CAP_READ;
+ cap_rights_set(rightsp, CAP_READ);
break;
case O_RDWR:
- rights |= CAP_READ;
+ cap_rights_set(rightsp, CAP_READ);
/* FALLTHROUGH */
case O_WRONLY:
- rights |= CAP_WRITE;
+ cap_rights_set(rightsp, CAP_WRITE);
if (!(flags & (O_APPEND | O_TRUNC)))
- rights |= CAP_SEEK;
+ cap_rights_set(rightsp, CAP_SEEK);
break;
}
}
if (flags & O_CREAT)
- rights |= CAP_CREATE;
+ cap_rights_set(rightsp, CAP_CREATE);
if (flags & O_TRUNC)
- rights |= CAP_FTRUNCATE;
+ cap_rights_set(rightsp, CAP_FTRUNCATE);
if (flags & (O_SYNC | O_FSYNC))
- rights |= CAP_FSYNC;
+ cap_rights_set(rightsp, CAP_FSYNC);
if (flags & (O_EXLOCK | O_SHLOCK))
- rights |= CAP_FLOCK;
-
- return (rights);
+ cap_rights_set(rightsp, CAP_FLOCK);
}
/*
@@ -1051,12 +1053,13 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
int cmode;
int indx = -1, error;
struct nameidata nd;
- cap_rights_t rights_needed = CAP_LOOKUP;
+ cap_rights_t rights;
AUDIT_ARG_FFLAGS(flags);
AUDIT_ARG_MODE(mode);
/* XXX: audit dirfd */
- rights_needed |= flags_to_rights(flags);
+ cap_rights_init(&rights, CAP_LOOKUP);
+ flags_to_rights(flags, &rights);
/*
* Only one of the O_EXEC, O_RDONLY, O_WRONLY and O_RDWR flags
* may be specified.
@@ -1084,7 +1087,7 @@ kern_openat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
fp->f_flag = flags & FMASK;
cmode = ((mode &~ fdp->fd_cmask) & ALLPERMS) &~ S_ISTXT;
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
- rights_needed, td);
+ &rights, td);
td->td_dupfd = -1; /* XXX check for fdopen */
error = vn_open(&nd, &flags, cmode, fp);
if (error) {
@@ -1258,6 +1261,7 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
int error;
int whiteout = 0;
struct nameidata nd;
+ cap_rights_t rights;
AUDIT_ARG_MODE(mode);
AUDIT_ARG_DEV(dev);
@@ -1285,7 +1289,7 @@ kern_mknodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
- pathseg, path, fd, CAP_MKNODAT, td);
+ pathseg, path, fd, cap_rights_init(&rights, CAP_MKNODAT), td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -1398,6 +1402,7 @@ kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
{
struct mount *mp;
struct vattr vattr;
+ cap_rights_t rights;
int error;
struct nameidata nd;
@@ -1405,7 +1410,7 @@ kern_mkfifoat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
- pathseg, path, fd, CAP_MKFIFOAT, td);
+ pathseg, path, fd, cap_rights_init(&rights, CAP_MKFIFOAT), td);
if ((error = namei(&nd)) != 0)
return (error);
if (nd.ni_vp != NULL) {
@@ -1541,6 +1546,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
struct vnode *vp;
struct mount *mp;
struct nameidata nd;
+ cap_rights_t rights;
int error;
bwillwrite();
@@ -1559,7 +1565,7 @@ kern_linkat(struct thread *td, int fd1, int fd2, char *path1, char *path2,
return (error);
}
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE2,
- segflg, path2, fd2, CAP_LINKAT, td);
+ segflg, path2, fd2, cap_rights_init(&rights, CAP_LINKAT), td);
if ((error = namei(&nd)) == 0) {
if (nd.ni_vp != NULL) {
if (nd.ni_dvp == nd.ni_vp)
@@ -1640,6 +1646,7 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2,
char *syspath;
int error;
struct nameidata nd;
+ cap_rights_t rights;
if (segflg == UIO_SYSSPACE) {
syspath = path1;
@@ -1652,7 +1659,7 @@ kern_symlinkat(struct thread *td, char *path1, int fd, char *path2,
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
- segflg, path2, fd, CAP_SYMLINKAT, td);
+ segflg, path2, fd, cap_rights_init(&rights, CAP_SYMLINKAT), td);
if ((error = namei(&nd)) != 0)
goto out;
if (nd.ni_vp) {
@@ -1800,11 +1807,12 @@ kern_unlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
int error;
struct nameidata nd;
struct stat sb;
+ cap_rights_t rights;
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
- pathseg, path, fd, CAP_UNLINKAT, td);
+ pathseg, path, fd, cap_rights_init(&rights, CAP_UNLINKAT), td);
if ((error = namei(&nd)) != 0)
return (error == EINVAL ? EPERM : error);
vp = nd.ni_vp;
@@ -1880,10 +1888,12 @@ sys_lseek(td, uap)
} */ *uap;
{
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
- if ((error = fget(td, uap->fd, CAP_SEEK, &fp)) != 0)
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_SEEK), &fp);
+ if (error != 0)
return (error);
error = (fp->f_ops->fo_flags & DFLAG_SEEKABLE) != 0 ?
fo_seek(fp, uap->offset, uap->whence, td) : ESPIPE;
@@ -2026,6 +2036,7 @@ kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
struct ucred *cred, *tmpcred;
struct vnode *vp;
struct nameidata nd;
+ cap_rights_t rights;
int error;
/*
@@ -2042,7 +2053,8 @@ kern_accessat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
cred = tmpcred = td->td_ucred;
AUDIT_ARG_VALUE(amode);
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | LOCKSHARED | LOCKLEAF |
- AUDITVNODE1, pathseg, path, fd, CAP_FSTAT, td);
+ AUDITVNODE1, pathseg, path, fd, cap_rights_init(&rights, CAP_FSTAT),
+ td);
if ((error = namei(&nd)) != 0)
goto out1;
vp = nd.ni_vp;
@@ -2244,6 +2256,7 @@ kern_statat_vnhook(struct thread *td, int flag, int fd, char *path,
{
struct nameidata nd;
struct stat sb;
+ cap_rights_t rights;
int error;
if (flag & ~AT_SYMLINK_NOFOLLOW)
@@ -2251,7 +2264,7 @@ kern_statat_vnhook(struct thread *td, int flag, int fd, char *path,
NDINIT_ATRIGHTS(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :
FOLLOW) | LOCKSHARED | LOCKLEAF | AUDITVNODE1, pathseg, path, fd,
- CAP_FSTAT, td);
+ cap_rights_init(&rights, CAP_FSTAT), td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -2663,12 +2676,13 @@ kern_chflagsat(struct thread *td, int fd, const char *path,
enum uio_seg pathseg, u_long flags, int atflag)
{
struct nameidata nd;
+ cap_rights_t rights;
int error, follow;
AUDIT_ARG_FFLAGS(flags);
follow = (atflag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
- CAP_FCHFLAGS, td);
+ cap_rights_init(&rights, CAP_FCHFLAGS), td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2695,12 +2709,14 @@ sys_fchflags(td, uap)
} */ *uap;
{
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_FFLAGS(uap->flags);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FCHFLAGS,
- &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_FCHFLAGS), &fp);
+ if (error != 0)
return (error);
#ifdef AUDIT
vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
@@ -2820,11 +2836,12 @@ kern_fchmodat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
int error;
struct nameidata nd;
int follow;
+ cap_rights_t rights;
AUDIT_ARG_MODE(mode);
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
- CAP_FCHMOD, td);
+ cap_rights_init(&rights, CAP_FCHMOD), td);
if ((error = namei(&nd)) != 0)
return (error);
NDFREE(&nd, NDF_ONLY_PNBUF);
@@ -2846,12 +2863,13 @@ int
sys_fchmod(struct thread *td, struct fchmod_args *uap)
{
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_MODE(uap->mode);
- error = fget(td, uap->fd, CAP_FCHMOD, &fp);
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FCHMOD), &fp);
if (error != 0)
return (error);
error = fo_chmod(fp, uap->mode, td->td_ucred, td);
@@ -2949,12 +2967,13 @@ kern_fchownat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
int uid, int gid, int flag)
{
struct nameidata nd;
+ cap_rights_t rights;
int error, follow;
AUDIT_ARG_OWNER(uid, gid);
follow = (flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW : FOLLOW;
NDINIT_ATRIGHTS(&nd, LOOKUP, follow | AUDITVNODE1, pathseg, path, fd,
- CAP_FCHOWN, td);
+ cap_rights_init(&rights, CAP_FCHOWN), td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3016,11 +3035,12 @@ sys_fchown(td, uap)
} */ *uap;
{
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(uap->fd);
AUDIT_ARG_OWNER(uap->uid, uap->gid);
- error = fget(td, uap->fd, CAP_FCHOWN, &fp);
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_FCHOWN), &fp);
if (error != 0)
return (error);
error = fo_chown(fp, uap->uid, uap->gid, td->td_ucred, td);
@@ -3155,12 +3175,13 @@ kern_utimesat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
{
struct nameidata nd;
struct timespec ts[2];
+ cap_rights_t rights;
int error;
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
return (error);
NDINIT_ATRIGHTS(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, fd,
- CAP_FUTIMES, td);
+ cap_rights_init(&rights, CAP_FUTIMES), td);
if ((error = namei(&nd)) != 0)
return (error);
@@ -3238,12 +3259,15 @@ kern_futimes(struct thread *td, int fd, struct timeval *tptr,
{
struct timespec ts[2];
struct file *fp;
+ cap_rights_t rights;
int error;
AUDIT_ARG_FD(fd);
if ((error = getutimes(tptr, tptrseg, ts)) != 0)
return (error);
- if ((error = getvnode(td->td_proc->p_fd, fd, CAP_FUTIMES, &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_FUTIMES), &fp);
+ if (error != 0)
return (error);
#ifdef AUDIT
vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
@@ -3390,10 +3414,13 @@ sys_fsync(td, uap)
struct vnode *vp;
struct mount *mp;
struct file *fp;
+ cap_rights_t rights;
int error, lock_flags;
AUDIT_ARG_FD(uap->fd);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_FSYNC, &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_FSYNC), &fp);
+ if (error != 0)
return (error);
vp = fp->f_vnode;
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
@@ -3472,15 +3499,17 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
struct mount *mp = NULL;
struct vnode *tvp, *fvp, *tdvp;
struct nameidata fromnd, tond;
+ cap_rights_t rights;
int error;
bwillwrite();
#ifdef MAC
NDINIT_ATRIGHTS(&fromnd, DELETE, LOCKPARENT | LOCKLEAF | SAVESTART |
- AUDITVNODE1, pathseg, old, oldfd, CAP_RENAMEAT, td);
+ AUDITVNODE1, pathseg, old, oldfd,
+ cap_rights_init(&rights, CAP_RENAMEAT), td);
#else
NDINIT_ATRIGHTS(&fromnd, DELETE, WANTPARENT | SAVESTART | AUDITVNODE1,
- pathseg, old, oldfd, CAP_RENAMEAT, td);
+ pathseg, old, oldfd, cap_rights_init(&rights, CAP_RENAMEAT), td);
#endif
if ((error = namei(&fromnd)) != 0)
@@ -3502,7 +3531,8 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
goto out1;
}
NDINIT_ATRIGHTS(&tond, RENAME, LOCKPARENT | LOCKLEAF | NOCACHE |
- SAVESTART | AUDITVNODE2, pathseg, new, newfd, CAP_LINKAT, td);
+ SAVESTART | AUDITVNODE2, pathseg, new, newfd,
+ cap_rights_init(&rights, CAP_LINKAT), td);
if (fromnd.ni_vp->v_type == VDIR)
tond.ni_cnd.cn_flags |= WILLBEDIR;
if ((error = namei(&tond)) != 0) {
@@ -3531,8 +3561,8 @@ kern_renameat(struct thread *td, int oldfd, char *old, int newfd, char *new,
* If the target already exists we require CAP_UNLINKAT
* from 'newfd'.
*/
- error = cap_check(tond.ni_filecaps.fc_rights,
- CAP_UNLINKAT);
+ error = cap_check(&tond.ni_filecaps.fc_rights,
+ cap_rights_init(&rights, CAP_UNLINKAT));
if (error != 0)
goto out;
}
@@ -3630,6 +3660,7 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg,
struct mount *mp;
struct vnode *vp;
struct vattr vattr;
+ cap_rights_t rights;
int error;
struct nameidata nd;
@@ -3637,7 +3668,7 @@ kern_mkdirat(struct thread *td, int fd, char *path, enum uio_seg segflg,
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, CREATE, LOCKPARENT | SAVENAME | AUDITVNODE1,
- segflg, path, fd, CAP_MKDIRAT, td);
+ segflg, path, fd, cap_rights_init(&rights, CAP_MKDIRAT), td);
nd.ni_cnd.cn_flags |= WILLBEDIR;
if ((error = namei(&nd)) != 0)
return (error);
@@ -3715,13 +3746,14 @@ kern_rmdirat(struct thread *td, int fd, char *path, enum uio_seg pathseg)
{
struct mount *mp;
struct vnode *vp;
+ cap_rights_t rights;
int error;
struct nameidata nd;
restart:
bwillwrite();
NDINIT_ATRIGHTS(&nd, DELETE, LOCKPARENT | LOCKLEAF | AUDITVNODE1,
- pathseg, path, fd, CAP_UNLINKAT, td);
+ pathseg, path, fd, cap_rights_init(&rights, CAP_UNLINKAT), td);
if ((error = namei(&nd)) != 0)
return (error);
vp = nd.ni_vp;
@@ -3806,6 +3838,7 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
struct uio auio, kuio;
struct iovec aiov, kiov;
struct dirent *dp, *edp;
+ cap_rights_t rights;
caddr_t dirbuf;
int error, eofflag, readcnt;
long loff;
@@ -3814,7 +3847,9 @@ kern_ogetdirentries(struct thread *td, struct ogetdirentries_args *uap,
/* XXX arbitrary sanity limit on `count'. */
if (uap->count > 64 * 1024)
return (EINVAL);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, uap->fd,
+ cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
fdrop(fp, td);
@@ -3967,6 +4002,7 @@ kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
struct file *fp;
struct uio auio;
struct iovec aiov;
+ cap_rights_t rights;
long loff;
int error, eofflag;
off_t foffset;
@@ -3975,7 +4011,9 @@ kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
if (count > IOSIZE_MAX)
return (EINVAL);
auio.uio_resid = count;
- if ((error = getvnode(td->td_proc->p_fd, fd, CAP_READ, &fp)) != 0)
+ error = getvnode(td->td_proc->p_fd, fd,
+ cap_rights_init(&rights, CAP_READ), &fp);
+ if (error != 0)
return (error);
if ((fp->f_flag & FREAD) == 0) {
fdrop(fp, td);
@@ -4138,12 +4176,12 @@ out:
* entry is held upon returning.
*/
int
-getvnode(struct filedesc *fdp, int fd, cap_rights_t rights, struct file **fpp)
+getvnode(struct filedesc *fdp, int fd, cap_rights_t *rightsp, struct file **fpp)
{
struct file *fp;
int error;
- error = fget_unlocked(fdp, fd, rights, 0, &fp, NULL);
+ error = fget_unlocked(fdp, fd, rightsp, 0, &fp, NULL);
if (error != 0)
return (error);
@@ -4466,11 +4504,12 @@ kern_posix_fallocate(struct thread *td, int fd, off_t offset, off_t len)
struct file *fp;
struct mount *mp;
struct vnode *vp;
+ cap_rights_t rights;
off_t olen, ooffset;
int error;
fp = NULL;
- error = fget(td, fd, CAP_WRITE, &fp);
+ error = fget(td, fd, cap_rights_init(&rights, CAP_WRITE), &fp);
if (error != 0)
goto out;
@@ -4562,6 +4601,7 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,
struct fadvise_info *fa, *new;
struct file *fp;
struct vnode *vp;
+ cap_rights_t rights;
off_t end;
int error;
@@ -4582,7 +4622,7 @@ kern_posix_fadvise(struct thread *td, int fd, off_t offset, off_t len,
return (EINVAL);
}
/* XXX: CAP_POSIX_FADVISE? */
- error = fget(td, fd, CAP_NONE, &fp);
+ error = fget(td, fd, cap_rights_init(&rights), &fp);
if (error != 0)
goto out;
diff --git a/sys/netsmb/smb_dev.c b/sys/netsmb/smb_dev.c
index 0efb282..279ae67 100644
--- a/sys/netsmb/smb_dev.c
+++ b/sys/netsmb/smb_dev.c
@@ -378,6 +378,7 @@ int
smb_dev2share(int fd, int mode, struct smb_cred *scred,
struct smb_share **sspp, struct smb_dev **ssdp)
{
+ cap_rights_t rights;
struct file *fp, *fptmp;
struct smb_dev *sdp;
struct smb_share *ssp;
@@ -385,7 +386,7 @@ smb_dev2share(int fd, int mode, struct smb_cred *scred,
int error;
td = curthread;
- error = fget(td, fd, CAP_READ, &fp);
+ error = fget(td, fd, cap_rights_init(&rights, CAP_READ), &fp);
if (error)
return (error);
fptmp = td->td_fpop;
diff --git a/sys/nfsserver/nfs_srvkrpc.c b/sys/nfsserver/nfs_srvkrpc.c
index db69df9..85003b7 100644
--- a/sys/nfsserver/nfs_srvkrpc.c
+++ b/sys/nfsserver/nfs_srvkrpc.c
@@ -168,6 +168,7 @@ nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap)
struct file *fp;
struct nfsd_addsock_args addsockarg;
struct nfsd_nfsd_args nfsdarg;
+ cap_rights_t rights;
int error;
if (uap->flag & NFSSVC_ADDSOCK) {
@@ -175,7 +176,8 @@ nfssvc_nfsserver(struct thread *td, struct nfssvc_args *uap)
sizeof(addsockarg));
if (error)
return (error);
- error = fget(td, addsockarg.sock, CAP_SOCK_SERVER, &fp);
+ error = fget(td, addsockarg.sock,
+ cap_rights_init(&rights, CAP_SOCK_SERVER), &fp);
if (error)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
diff --git a/sys/security/audit/audit.h b/sys/security/audit/audit.h
index dd55875..559d571 100644
--- a/sys/security/audit/audit.h
+++ b/sys/security/audit/audit.h
@@ -114,7 +114,7 @@ void audit_arg_auditon(union auditon_udata *udata);
void audit_arg_file(struct proc *p, struct file *fp);
void audit_arg_argv(char *argv, int argc, int length);
void audit_arg_envv(char *envv, int envc, int length);
-void audit_arg_rights(cap_rights_t rights);
+void audit_arg_rights(cap_rights_t *rightsp);
void audit_arg_fcntl_rights(uint32_t fcntlrights);
void audit_sysclose(struct thread *td, int fd);
void audit_cred_copy(struct ucred *src, struct ucred *dest);
diff --git a/sys/security/audit/audit_arg.c b/sys/security/audit/audit_arg.c
index 4927be0..2e86842 100644
--- a/sys/security/audit/audit_arg.c
+++ b/sys/security/audit/audit_arg.c
@@ -861,7 +861,7 @@ audit_arg_envv(char *envv, int envc, int length)
}
void
-audit_arg_rights(cap_rights_t rights)
+audit_arg_rights(cap_rights_t *rightsp)
{
struct kaudit_record *ar;
@@ -869,7 +869,7 @@ audit_arg_rights(cap_rights_t rights)
if (ar == NULL)
return;
- ar->k_ar.ar_arg_rights = rights;
+ ar->k_ar.ar_arg_rights = *rightsp;
ARG_SET_VALID(ar, ARG_RIGHTS);
}
diff --git a/sys/security/audit/audit_bsm.c b/sys/security/audit/audit_bsm.c
index 03b3c23..9f29ece 100644
--- a/sys/security/audit/audit_bsm.c
+++ b/sys/security/audit/audit_bsm.c
@@ -1611,14 +1611,13 @@ kaudit_to_bsm(struct kaudit_record *kar, struct au_record **pau)
}
break;
- case AUE_CAP_NEW:
case AUE_CAP_RIGHTS_LIMIT:
/*
* XXXRW/XXXJA: Would be nice to audit socket/etc information.
*/
FD_VNODE1_TOKENS;
if (ARG_IS_VALID(kar, ARG_RIGHTS)) {
- tok = au_to_arg64(2, "rights", ar->ar_arg_rights);
+ tok = au_to_rights(&ar->ar_arg_rights);
kau_write(rec, tok);
}
break;
diff --git a/sys/security/audit/audit_private.h b/sys/security/audit/audit_private.h
index e23ba08..b5c373a 100644
--- a/sys/security/audit/audit_private.h
+++ b/sys/security/audit/audit_private.h
@@ -41,6 +41,7 @@
#error "no user-serviceable parts inside"
#endif
+#include <sys/caprights.h>
#include <sys/ipc.h>
#include <sys/socket.h>
#include <sys/ucred.h>
diff --git a/sys/security/audit/bsm_token.c b/sys/security/audit/bsm_token.c
index 6d0d67f..763d597 100644
--- a/sys/security/audit/bsm_token.c
+++ b/sys/security/audit/bsm_token.c
@@ -835,6 +835,22 @@ au_to_process_ex(au_id_t auid, uid_t euid, gid_t egid, uid_t ruid,
tid));
}
+token_t *
+au_to_rights(cap_rights_t *rightsp)
+{
+ token_t *t;
+ u_char *dptr;
+ int i;
+
+ GET_TOKEN_AREA(t, dptr, sizeof(u_char) + sizeof(*rightsp));
+
+ ADD_U_CHAR(dptr, AUT_RIGHTS);
+ for (i = 0; i < nitems(rightsp->cr_rights); i++)
+ ADD_U_INT64(dptr, rightsp->cr_rights[i]);
+
+ return (t);
+}
+
/*
* token ID 1 byte
* error status 1 byte
diff --git a/sys/security/mac/mac_syscalls.c b/sys/security/mac/mac_syscalls.c
index ff55ec9..6405586 100644
--- a/sys/security/mac/mac_syscalls.c
+++ b/sys/security/mac/mac_syscalls.c
@@ -229,6 +229,7 @@ sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
struct vnode *vp;
struct pipe *pipe;
struct socket *so;
+ cap_rights_t rights;
short label_type;
int error;
@@ -248,7 +249,7 @@ sys___mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
}
buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
- error = fget(td, uap->fd, CAP_MAC_GET, &fp);
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_MAC_GET), &fp);
if (error)
goto out;
@@ -425,6 +426,7 @@ sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
struct mount *mp;
struct vnode *vp;
struct mac mac;
+ cap_rights_t rights;
char *buffer;
int error;
@@ -443,7 +445,7 @@ sys___mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
return (error);
}
- error = fget(td, uap->fd, CAP_MAC_SET, &fp);
+ error = fget(td, uap->fd, cap_rights_init(&rights, CAP_MAC_SET), &fp);
if (error)
goto out;
diff --git a/sys/sys/_types.h b/sys/sys/_types.h
index 34d1edb..ffef9d8 100644
--- a/sys/sys/_types.h
+++ b/sys/sys/_types.h
@@ -38,7 +38,6 @@
typedef __uint32_t __blksize_t; /* file block size */
typedef __int64_t __blkcnt_t; /* file block count */
typedef __int32_t __clockid_t; /* clock_gettime()... */
-typedef __uint64_t __cap_rights_t; /* capability rights */
typedef __uint32_t __fflags_t; /* file flags */
typedef __uint64_t __fsblkcnt_t;
typedef __uint64_t __fsfilcnt_t;
diff --git a/sys/sys/capability.h b/sys/sys/capability.h
index ec63de7..e5b9ec7 100644
--- a/sys/sys/capability.h
+++ b/sys/sys/capability.h
@@ -42,9 +42,16 @@
#include <sys/cdefs.h>
#include <sys/param.h>
+#include <sys/caprights.h>
#include <sys/file.h>
#include <sys/fcntl.h>
+#ifndef _KERNEL
+#include <stdbool.h>
+#endif
+
+#define CAPRIGHT(idx, bit) ((1ULL << (57 + (idx))) | (bit))
+
/*
* Possible rights on capabilities.
*
@@ -59,29 +66,31 @@
* involve reads or writes depending a great deal on context.
*/
-#define CAP_NONE 0x0000000000000000ULL
+/* INDEX 0 */
/*
* General file I/O.
*/
/* Allows for openat(O_RDONLY), read(2), readv(2). */
-#define CAP_READ 0x0000000000000001ULL
+#define CAP_READ CAPRIGHT(0, 0x0000000000000001ULL)
/* Allows for openat(O_WRONLY | O_APPEND), write(2), writev(2). */
-#define CAP_WRITE 0x0000000000000002ULL
+#define CAP_WRITE CAPRIGHT(0, 0x0000000000000002ULL)
+/* Allows for lseek(fd, 0, SEEK_CUR). */
+#define CAP_SEEK_TELL CAPRIGHT(0, 0x0000000000000004ULL)
/* Allows for lseek(2). */
-#define CAP_SEEK 0x0000000000000080ULL
+#define CAP_SEEK (CAP_SEEK_TELL | 0x0000000000000008ULL)
/* Allows for pread(2), preadv(2). */
#define CAP_PREAD (CAP_SEEK | CAP_READ)
/* Allows for openat(O_WRONLY) (without O_APPEND), pwrite(2), pwritev(2). */
#define CAP_PWRITE (CAP_SEEK | CAP_WRITE)
/* Allows for mmap(PROT_NONE). */
-#define CAP_MMAP 0x0000000000000004ULL
+#define CAP_MMAP CAPRIGHT(0, 0x0000000000000010ULL)
/* Allows for mmap(PROT_READ). */
#define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ)
/* Allows for mmap(PROT_WRITE). */
#define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE)
/* Allows for mmap(PROT_EXEC). */
-#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL)
+#define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000020ULL)
/* Allows for mmap(PROT_READ | PROT_WRITE). */
#define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W)
/* Allows for mmap(PROT_READ | PROT_EXEC). */
@@ -91,67 +100,67 @@
/* Allows for mmap(PROT_READ | PROT_WRITE | PROT_EXEC). */
#define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X)
/* Allows for openat(O_CREAT). */
-#define CAP_CREATE 0x0000000000080000ULL
+#define CAP_CREATE CAPRIGHT(0, 0x0000000000000040ULL)
/* Allows for openat(O_EXEC) and fexecve(2) in turn. */
-#define CAP_FEXECVE 0x0000000000000010ULL
+#define CAP_FEXECVE CAPRIGHT(0, 0x0000000000000080ULL)
/* Allows for openat(O_SYNC), openat(O_FSYNC), fsync(2). */
-#define CAP_FSYNC 0x0000000000000020ULL
+#define CAP_FSYNC CAPRIGHT(0, 0x0000000000000100ULL)
/* Allows for openat(O_TRUNC), ftruncate(2). */
-#define CAP_FTRUNCATE 0x0000000000000040ULL
-
-/* VFS methods. */
-#define CAP_FCHDIR 0x0000000000000200ULL
-#define CAP_FCHFLAGS 0x0000000000000100ULL
-#define CAP_CHFLAGSAT CAP_FCHFLAGS
-#define CAP_FCHMOD 0x0000000000000400ULL
-#define CAP_FCHMODAT CAP_FCHMOD
-#define CAP_FCHOWN 0x0000000000000800ULL
-#define CAP_FCHOWNAT CAP_FCHOWN
-#define CAP_FCNTL 0x0000000000001000ULL
-#define CAP_FLOCK 0x0000000000004000ULL
-#define CAP_FPATHCONF 0x0000000000002000ULL
-#define CAP_FSCK 0x0000000000008000ULL
-#define CAP_FSTAT 0x0000000000010000ULL
-#define CAP_FSTATAT CAP_FSTAT
-#define CAP_FSTATFS 0x0000000000020000ULL
-#define CAP_FUTIMES 0x0000000000040000ULL
-#define CAP_FUTIMESAT CAP_FUTIMES
-#define CAP_LINKAT 0x0000000000400000ULL
-#define CAP_MKDIRAT 0x0000000000200000ULL
-#define CAP_MKFIFOAT 0x0000000000800000ULL
-#define CAP_MKNODAT 0x0080000000000000ULL
-#define CAP_RENAMEAT 0x0200000000000000ULL
-#define CAP_SYMLINKAT 0x0100000000000000ULL
-#define CAP_UNLINKAT 0x0000000000100000ULL
+#define CAP_FTRUNCATE CAPRIGHT(0, 0x0000000000000200ULL)
/* Lookups - used to constrain *at() calls. */
-#define CAP_LOOKUP 0x0000000001000000ULL
+#define CAP_LOOKUP CAPRIGHT(0, 0x0000000000000400ULL)
+
+/* VFS methods. */
+#define CAP_FCHDIR CAPRIGHT(0, 0x0000000000000800ULL)
+#define CAP_FCHFLAGS CAPRIGHT(0, 0x0000000000001000ULL)
+#define CAP_CHFLAGSAT (CAP_FCHFLAGS | CAP_LOOKUP)
+#define CAP_FCHMOD CAPRIGHT(0, 0x0000000000002000ULL)
+#define CAP_FCHMODAT (CAP_FCHMOD | CAP_LOOKUP)
+#define CAP_FCHOWN CAPRIGHT(0, 0x0000000000004000ULL)
+#define CAP_FCHOWNAT (CAP_FCHOWN | CAP_LOOKUP)
+#define CAP_FCNTL CAPRIGHT(0, 0x0000000000008000ULL)
+#define CAP_FLOCK CAPRIGHT(0, 0x0000000000010000ULL)
+#define CAP_FPATHCONF CAPRIGHT(0, 0x0000000000020000ULL)
+#define CAP_FSCK CAPRIGHT(0, 0x0000000000040000ULL)
+#define CAP_FSTAT CAPRIGHT(0, 0x0000000000080000ULL)
+#define CAP_FSTATAT (CAP_FSTAT | CAP_LOOKUP)
+#define CAP_FSTATFS CAPRIGHT(0, 0x0000000000100000ULL)
+#define CAP_FUTIMES CAPRIGHT(0, 0x0000000000200000ULL)
+#define CAP_FUTIMESAT (CAP_FUTIMES | CAP_LOOKUP)
+#define CAP_LINKAT CAPRIGHT(0, 0x0000000000400000ULL)
+#define CAP_MKDIRAT CAPRIGHT(0, 0x0000000000800000ULL)
+#define CAP_MKFIFOAT CAPRIGHT(0, 0x0000000001000000ULL)
+#define CAP_MKNODAT CAPRIGHT(0, 0x0000000002000000ULL)
+#define CAP_RENAMEAT CAPRIGHT(0, 0x0000000004000000ULL)
+#define CAP_SYMLINKAT CAPRIGHT(0, 0x0000000008000000ULL)
+#define CAP_UNLINKAT CAPRIGHT(0, 0x0000000010000000ULL)
/* Extended attributes. */
-#define CAP_EXTATTR_DELETE 0x0000000002000000ULL
-#define CAP_EXTATTR_GET 0x0000000004000000ULL
-#define CAP_EXTATTR_LIST 0x0000000008000000ULL
-#define CAP_EXTATTR_SET 0x0000000010000000ULL
+#define CAP_EXTATTR_DELETE CAPRIGHT(0, 0x0000000020000000ULL)
+#define CAP_EXTATTR_GET CAPRIGHT(0, 0x0000000040000000ULL)
+#define CAP_EXTATTR_LIST CAPRIGHT(0, 0x0000000080000000ULL)
+#define CAP_EXTATTR_SET CAPRIGHT(0, 0x0000000100000000ULL)
/* Access Control Lists. */
-#define CAP_ACL_CHECK 0x0000000020000000ULL
-#define CAP_ACL_DELETE 0x0000000040000000ULL
-#define CAP_ACL_GET 0x0000000080000000ULL
-#define CAP_ACL_SET 0x0000000100000000ULL
+#define CAP_ACL_CHECK CAPRIGHT(0, 0x0000000200000000ULL)
+#define CAP_ACL_DELETE CAPRIGHT(0, 0x0000000400000000ULL)
+#define CAP_ACL_GET CAPRIGHT(0, 0x0000000800000000ULL)
+#define CAP_ACL_SET CAPRIGHT(0, 0x0000001000000000ULL)
/* Socket operations. */
-#define CAP_ACCEPT 0x0000000200000000ULL
-#define CAP_BIND 0x0000000400000000ULL
-#define CAP_CONNECT 0x0000000800000000ULL
-#define CAP_GETPEERNAME 0x0000001000000000ULL
-#define CAP_GETSOCKNAME 0x0000002000000000ULL
-#define CAP_GETSOCKOPT 0x0000004000000000ULL
-#define CAP_LISTEN 0x0000008000000000ULL
-#define CAP_PEELOFF 0x0000010000000000ULL
+#define CAP_ACCEPT CAPRIGHT(0, 0x0000002000000000ULL)
+#define CAP_BIND CAPRIGHT(0, 0x0000004000000000ULL)
+#define CAP_CONNECT CAPRIGHT(0, 0x0000008000000000ULL)
+#define CAP_GETPEERNAME CAPRIGHT(0, 0x0000010000000000ULL)
+#define CAP_GETSOCKNAME CAPRIGHT(0, 0x0000020000000000ULL)
+#define CAP_GETSOCKOPT CAPRIGHT(0, 0x0000040000000000ULL)
+#define CAP_LISTEN CAPRIGHT(0, 0x0000080000000000ULL)
+#define CAP_PEELOFF CAPRIGHT(0, 0x0000100000000000ULL)
#define CAP_RECV CAP_READ
#define CAP_SEND CAP_WRITE
-#define CAP_SETSOCKOPT 0x0000020000000000ULL
-#define CAP_SHUTDOWN 0x0000040000000000ULL
+#define CAP_SETSOCKOPT CAPRIGHT(0, 0x0000200000000000ULL)
+#define CAP_SHUTDOWN CAPRIGHT(0, 0x0000400000000000ULL)
#define CAP_SOCK_CLIENT \
(CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \
@@ -161,56 +170,69 @@
CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \
CAP_SETSOCKOPT | CAP_SHUTDOWN)
+/* All used bits for index 0. */
+#define CAP_ALL0 CAPRIGHT(0, 0x00007FFFFFFFFFFFULL)
+
+/* Available bits for index 0. */
+#define CAP_UNUSED0_48 CAPRIGHT(0, 0x0000800000000000ULL)
+/* ... */
+#define CAP_UNUSED0_57 CAPRIGHT(0, 0x0100000000000000ULL)
+
+/* INDEX 1 */
+
/* Mandatory Access Control. */
-#define CAP_MAC_GET 0x0000080000000000ULL
-#define CAP_MAC_SET 0x0000100000000000ULL
+#define CAP_MAC_GET CAPRIGHT(1, 0x0000000000000001ULL)
+#define CAP_MAC_SET CAPRIGHT(1, 0x0000000000000002ULL)
/* Methods on semaphores. */
-#define CAP_SEM_GETVALUE 0x0000200000000000ULL
-#define CAP_SEM_POST 0x0000400000000000ULL
-#define CAP_SEM_WAIT 0x0000800000000000ULL
+#define CAP_SEM_GETVALUE CAPRIGHT(1, 0x0000000000000004ULL)
+#define CAP_SEM_POST CAPRIGHT(1, 0x0000000000000008ULL)
+#define CAP_SEM_WAIT CAPRIGHT(1, 0x0000000000000010ULL)
/* kqueue events. */
-#define CAP_POLL_EVENT 0x0001000000000000ULL
-#define CAP_POST_EVENT 0x0002000000000000ULL
+#define CAP_POLL_EVENT CAPRIGHT(1, 0x0000000000000020ULL)
+#define CAP_POST_EVENT CAPRIGHT(1, 0x0000000000000040ULL)
/* Strange and powerful rights that should not be given lightly. */
-#define CAP_IOCTL 0x0004000000000000ULL
-#define CAP_TTYHOOK 0x0008000000000000ULL
+#define CAP_IOCTL CAPRIGHT(1, 0x0000000000000080ULL)
+#define CAP_TTYHOOK CAPRIGHT(1, 0x0000000000000100ULL)
/* Process management via process descriptors. */
-#define CAP_PDGETPID 0x0010000000000000ULL
-#define CAP_PDWAIT 0x0020000000000000ULL
-#define CAP_PDKILL 0x0040000000000000ULL
+#define CAP_PDGETPID CAPRIGHT(1, 0x0000000000000200ULL)
+#define CAP_PDWAIT CAPRIGHT(1, 0x0000000000000400ULL)
+#define CAP_PDKILL CAPRIGHT(1, 0x0000000000000800ULL)
/*
* Rights that allow to use bindat(2) and connectat(2) syscalls on a
* directory descriptor.
*/
-#define CAP_BINDAT 0x0400000000000000ULL
-#define CAP_CONNECTAT 0x0800000000000000ULL
-
-/* The mask of all valid method rights. */
-#define CAP_MASK_VALID 0x0fffffffffffffffULL
-#define CAP_ALL CAP_MASK_VALID
-
-/* Available bits. */
-#define CAP_UNUSED3 0x1000000000000000ULL
-#define CAP_UNUSED2 0x2000000000000000ULL
-#define CAP_UNUSED1 0x4000000000000000ULL
-#define CAP_UNUSED0 0x8000000000000000ULL
-
-/*
- * The following defines are provided for backward API compatibility and
- * should not be used in new code.
- */
-#define CAP_MAPEXEC CAP_MMAP_X
-#define CAP_DELETE CAP_UNLINKAT
-#define CAP_MKDIR CAP_MKDIRAT
-#define CAP_RMDIR CAP_UNLINKAT
-#define CAP_MKFIFO CAP_MKFIFOAT
-#define CAP_MKNOD CAP_MKNODAT
-#define CAP_SOCK_ALL (CAP_SOCK_CLIENT | CAP_SOCK_SERVER)
+#define CAP_BINDAT CAPRIGHT(1, 0x0000000000001000ULL)
+#define CAP_CONNECTAT CAPRIGHT(1, 0x0000000000002000ULL)
+
+/* All used bits for index 1. */
+#define CAP_ALL1 CAPRIGHT(1, 0x0000000000003FFFULL)
+
+/* Available bits for index 1. */
+#define CAP_UNUSED1_15 CAPRIGHT(1, 0x0000000000004000ULL)
+/* ... */
+#define CAP_UNUSED1_57 CAPRIGHT(1, 0x0100000000000000ULL)
+
+#define CAP_ALL(rights) do { \
+ (rights)->cr_rights[0] = \
+ ((uint64_t)CAP_RIGHTS_VERSION << 62) | CAP_ALL0; \
+ (rights)->cr_rights[1] = CAP_ALL1; \
+} while (0)
+
+#define CAP_NONE(rights) do { \
+ (rights)->cr_rights[0] = \
+ ((uint64_t)CAP_RIGHTS_VERSION << 62) | CAPRIGHT(0, 0ULL); \
+ (rights)->cr_rights[1] = CAPRIGHT(1, 0ULL); \
+} while (0)
+
+#define CAPRVER(right) ((int)((right) >> 62))
+#define CAPVER(rights) CAPRVER((rights)->cr_rights[0])
+#define CAPARSIZE(rights) (CAPVER(rights) + 2)
+#define CAPIDXBIT(right) ((int)(((right) >> 57) & 0x1F))
/*
* Allowed fcntl(2) commands.
@@ -230,6 +252,27 @@
#define CAP_IOCTLS_ALL SSIZE_MAX
+#define cap_rights_init(...) \
+ __cap_rights_init(CAP_RIGHTS_VERSION, __VA_ARGS__, 0ULL)
+cap_rights_t *__cap_rights_init(int version, cap_rights_t *rights, ...);
+
+#define cap_rights_set(rights, ...) \
+ __cap_rights_set((rights), __VA_ARGS__, 0ULL)
+void __cap_rights_set(cap_rights_t *rights, ...);
+
+#define cap_rights_clear(rights, ...) \
+ __cap_rights_clear((rights), __VA_ARGS__, 0ULL)
+void __cap_rights_clear(cap_rights_t *rights, ...);
+
+#define cap_rights_is_set(rights, ...) \
+ __cap_rights_is_set((rights), __VA_ARGS__, 0ULL)
+bool __cap_rights_is_set(const cap_rights_t *rights, ...);
+
+bool cap_rights_is_valid(const cap_rights_t *rights);
+void cap_rights_merge(cap_rights_t *dst, const cap_rights_t *src);
+void cap_rights_remove(cap_rights_t *dst, const cap_rights_t *src);
+bool cap_rights_contains(const cap_rights_t *big, const cap_rights_t *little);
+
#ifdef _KERNEL
#include <sys/systm.h>
@@ -241,17 +284,17 @@ struct filedesc;
/*
* Test whether a capability grants the requested rights.
*/
-int cap_check(cap_rights_t have, cap_rights_t need);
+int cap_check(const cap_rights_t *havep, const cap_rights_t *needp);
/*
* Convert capability rights into VM access flags.
*/
-u_char cap_rights_to_vmprot(cap_rights_t have);
+u_char cap_rights_to_vmprot(cap_rights_t *havep);
/*
* For the purposes of procstat(1) and similar tools, allow kern_descrip.c to
* extract the rights from a capability.
*/
-cap_rights_t cap_rights(struct filedesc *fdp, int fd);
+cap_rights_t *cap_rights(struct filedesc *fdp, int fd);
int cap_ioctl_check(struct filedesc *fdp, int fd, u_long cmd);
int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd);
@@ -259,18 +302,11 @@ int cap_fcntl_check(struct filedesc *fdp, int fd, int cmd);
#else /* !_KERNEL */
__BEGIN_DECLS
-#include <stdbool.h>
-
/*
* cap_enter(): Cause the process to enter capability mode, which will
* prevent it from directly accessing global namespaces. System calls will
* be limited to process-local, process-inherited, or file descriptor
* operations. If already in capability mode, a no-op.
- *
- * Currently, process-inherited operations are not properly handled -- in
- * particular, we're interested in things like waitpid(2), kill(2), etc,
- * being properly constrained. One possible solution is to introduce process
- * descriptors.
*/
int cap_enter(void);
@@ -288,11 +324,12 @@ int cap_getmode(u_int *modep);
/*
* Limits capability rights for the given descriptor (CAP_*).
*/
-int cap_rights_limit(int fd, cap_rights_t rights);
+int cap_rights_limit(int fd, const cap_rights_t *rights);
/*
- * Returns bitmask of capability rights for the given descriptor.
+ * Returns capability rights for the given descriptor.
*/
-int cap_rights_get(int fd, cap_rights_t *rightsp);
+#define cap_rights_get(fd, rights) __cap_rights_get(CAP_RIGHTS_VERSION, (fd), (rights))
+int __cap_rights_get(int version, int fd, cap_rights_t *rightsp);
/*
* Limits allowed ioctls for the given descriptor.
*/
@@ -312,10 +349,6 @@ int cap_fcntls_limit(int fd, uint32_t fcntlrights);
*/
int cap_fcntls_get(int fd, uint32_t *fcntlrightsp);
-/* For backward compatibility. */
-int cap_new(int fd, cap_rights_t rights);
-#define cap_getrights(fd, rightsp) cap_rights_get((fd), (rightsp))
-
__END_DECLS
#endif /* !_KERNEL */
diff --git a/sys/sys/caprights.h b/sys/sys/caprights.h
new file mode 100644
index 0000000..eb8e454
--- /dev/null
+++ b/sys/sys/caprights.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2013 FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Pawel Jakub Dawidek under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * 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.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_CAPRIGHTS_H_
+#define _SYS_CAPRIGHTS_H_
+
+/*
+ * The top two bits in the first element of the cr_rights[] array contain
+ * total number of elements in the array - 2. This means if those two bits are
+ * equal to 0, we have 2 array elements.
+ * The top two bits in all remaining array elements should be 0.
+ * The next five bits contain array index. Only one bit is used and bit position
+ * in this five-bits range defines array index. This means there can be at most
+ * five array elements.
+ */
+#define CAP_RIGHTS_VERSION_00 0
+/*
+#define CAP_RIGHTS_VERSION_01 1
+#define CAP_RIGHTS_VERSION_02 2
+#define CAP_RIGHTS_VERSION_03 3
+*/
+#define CAP_RIGHTS_VERSION CAP_RIGHTS_VERSION_00
+
+struct cap_rights {
+ uint64_t cr_rights[CAP_RIGHTS_VERSION + 2];
+};
+
+#ifndef _CAP_RIGHTS_T_DECLARED
+#define _CAP_RIGHTS_T_DECLARED
+typedef struct cap_rights cap_rights_t;
+#endif
+
+#endif /* !_SYS_CAPRIGHTS_H_ */
diff --git a/sys/sys/file.h b/sys/sys/file.h
index 72c512f..7b373f0 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -217,12 +217,12 @@ extern int maxfiles; /* kernel limit on number of open files */
extern int maxfilesperproc; /* per process limit on number of open files */
extern volatile int openfiles; /* actual number of open files */
-int fget(struct thread *td, int fd, cap_rights_t rights, struct file **fpp);
-int fget_mmap(struct thread *td, int fd, cap_rights_t rights,
+int fget(struct thread *td, int fd, cap_rights_t *rightsp, struct file **fpp);
+int fget_mmap(struct thread *td, int fd, cap_rights_t *rightsp,
u_char *maxprotp, struct file **fpp);
-int fget_read(struct thread *td, int fd, cap_rights_t rights,
+int fget_read(struct thread *td, int fd, cap_rights_t *rightsp,
struct file **fpp);
-int fget_write(struct thread *td, int fd, cap_rights_t rights,
+int fget_write(struct thread *td, int fd, cap_rights_t *rightsp,
struct file **fpp);
int _fdrop(struct file *fp, struct thread *td);
@@ -248,17 +248,18 @@ fo_sendfile_t vn_sendfile;
fo_seek_t vn_seek;
void finit(struct file *, u_int, short, void *, struct fileops *);
-int fgetvp(struct thread *td, int fd, cap_rights_t rights, struct vnode **vpp);
-int fgetvp_exec(struct thread *td, int fd, cap_rights_t rights,
+int fgetvp(struct thread *td, int fd, cap_rights_t *rightsp,
struct vnode **vpp);
-int fgetvp_rights(struct thread *td, int fd, cap_rights_t need,
+int fgetvp_exec(struct thread *td, int fd, cap_rights_t *rightsp,
+ struct vnode **vpp);
+int fgetvp_rights(struct thread *td, int fd, cap_rights_t *needrightsp,
struct filecaps *havecaps, struct vnode **vpp);
-int fgetvp_read(struct thread *td, int fd, cap_rights_t rights,
+int fgetvp_read(struct thread *td, int fd, cap_rights_t *rightsp,
struct vnode **vpp);
-int fgetvp_write(struct thread *td, int fd, cap_rights_t rights,
+int fgetvp_write(struct thread *td, int fd, cap_rights_t *rightsp,
struct vnode **vpp);
-int fgetsock(struct thread *td, int fd, cap_rights_t rights,
+int fgetsock(struct thread *td, int fd, cap_rights_t *rightsp,
struct socket **spp, u_int *fflagp);
void fputsock(struct socket *sp);
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index 9f73915..968ceff 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -33,6 +33,7 @@
#ifndef _SYS_FILEDESC_H_
#define _SYS_FILEDESC_H_
+#include <sys/caprights.h>
#include <sys/queue.h>
#include <sys/event.h>
#include <sys/lock.h>
@@ -108,10 +109,6 @@ struct filedesc_to_leader {
#ifdef _KERNEL
-#include <sys/systm.h> /* CTASSERT() */
-
-CTASSERT(sizeof(cap_rights_t) == sizeof(uint64_t));
-
/* Flags for do_dup() */
#define DUP_FIXED 0x1 /* Force fixed allocation. */
#define DUP_FCNTL 0x2 /* fcntl()-style errors. */
@@ -163,13 +160,13 @@ struct filedesc *fdshare(struct filedesc *fdp);
struct filedesc_to_leader *
filedesc_to_leader_alloc(struct filedesc_to_leader *old,
struct filedesc *fdp, struct proc *leader);
-int getvnode(struct filedesc *fdp, int fd, cap_rights_t rights,
+int getvnode(struct filedesc *fdp, int fd, cap_rights_t *rightsp,
struct file **fpp);
void mountcheckdirs(struct vnode *olddp, struct vnode *newdp);
void setugidsafety(struct thread *td);
/* Return a referenced file from an unlocked descriptor. */
-int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t needrights,
+int fget_unlocked(struct filedesc *fdp, int fd, cap_rights_t *needrightsp,
int needfcntl, struct file **fpp, cap_rights_t *haverightsp);
/* Requires a FILEDESC_{S,X}LOCK held and returns without a ref. */
diff --git a/sys/sys/ktrace.h b/sys/sys/ktrace.h
index b3e6be8..e9cfa6e 100644
--- a/sys/sys/ktrace.h
+++ b/sys/sys/ktrace.h
@@ -33,6 +33,8 @@
#ifndef _SYS_KTRACE_H_
#define _SYS_KTRACE_H_
+#include <sys/caprights.h>
+
/*
* operations to ktrace system call (KTROP(op))
*/
@@ -264,7 +266,10 @@ void ktrprocexit(struct thread *);
void ktrprocfork(struct proc *, struct proc *);
void ktruserret(struct thread *);
void ktrstruct(const char *, void *, size_t);
-void ktrcapfail(enum ktr_cap_fail_type, cap_rights_t, cap_rights_t);
+void ktrcapfail(enum ktr_cap_fail_type, const cap_rights_t *,
+ const cap_rights_t *);
+#define ktrcaprights(s) \
+ ktrstruct("caprights", (s), sizeof(cap_rights_t))
#define ktrsockaddr(s) \
ktrstruct("sockaddr", (s), ((struct sockaddr *)(s))->sa_len)
#define ktrstat(s) \
diff --git a/sys/sys/namei.h b/sys/sys/namei.h
index a9992f4..f1b1223 100644
--- a/sys/sys/namei.h
+++ b/sys/sys/namei.h
@@ -33,6 +33,7 @@
#ifndef _SYS_NAMEI_H_
#define _SYS_NAMEI_H_
+#include <sys/caprights.h>
#include <sys/filedesc.h>
#include <sys/queue.h>
#include <sys/uio.h>
@@ -158,32 +159,14 @@ struct nameidata {
NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, NULL, 0, td)
#define NDINIT_AT(ndp, op, flags, segflg, namep, dirfd, td) \
NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, 0, td)
-#define NDINIT_ATRIGHTS(ndp, op, flags, segflg, namep, dirfd, rights, td) \
- NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rights, td)
+#define NDINIT_ATRIGHTS(ndp, op, flags, segflg, namep, dirfd, rightsp, td) \
+ NDINIT_ALL(ndp, op, flags, segflg, namep, dirfd, NULL, rightsp, td)
#define NDINIT_ATVP(ndp, op, flags, segflg, namep, vp, td) \
NDINIT_ALL(ndp, op, flags, segflg, namep, AT_FDCWD, vp, 0, td)
-static __inline void
-NDINIT_ALL(struct nameidata *ndp,
- u_long op, u_long flags,
- enum uio_seg segflg,
- const char *namep,
- int dirfd,
- struct vnode *startdir,
- cap_rights_t rights,
- struct thread *td)
-{
- ndp->ni_cnd.cn_nameiop = op;
- ndp->ni_cnd.cn_flags = flags;
- ndp->ni_segflg = segflg;
- ndp->ni_dirp = namep;
- ndp->ni_dirfd = dirfd;
- ndp->ni_startdir = startdir;
- ndp->ni_strictrelative = 0;
- ndp->ni_rightsneeded = rights;
- filecaps_init(&ndp->ni_filecaps);
- ndp->ni_cnd.cn_thread = td;
-}
+void NDINIT_ALL(struct nameidata *ndp, u_long op, u_long flags,
+ enum uio_seg segflg, const char *namep, int dirfd, struct vnode *startdir,
+ cap_rights_t *rightsp, struct thread *td);
#define NDF_NO_DVP_RELE 0x00000001
#define NDF_NO_DVP_UNLOCK 0x00000002
diff --git a/sys/sys/procdesc.h b/sys/sys/procdesc.h
index cc8b716..4d77a05 100644
--- a/sys/sys/procdesc.h
+++ b/sys/sys/procdesc.h
@@ -92,8 +92,8 @@ struct procdesc {
* In-kernel interfaces to process descriptors.
*/
int procdesc_exit(struct proc *);
-int procdesc_find(struct thread *, int fd, cap_rights_t, struct proc **);
-int kern_pdgetpid(struct thread *, int fd, cap_rights_t, pid_t *pidp);
+int procdesc_find(struct thread *, int fd, cap_rights_t *, struct proc **);
+int kern_pdgetpid(struct thread *, int fd, cap_rights_t *, pid_t *pidp);
void procdesc_new(struct proc *, int);
void procdesc_finit(struct procdesc *, struct file *);
pid_t procdesc_pid(struct file *);
diff --git a/sys/sys/types.h b/sys/sys/types.h
index cc0bca8..03eaa60 100644
--- a/sys/sys/types.h
+++ b/sys/sys/types.h
@@ -88,8 +88,6 @@ typedef __blkcnt_t blkcnt_t;
#define _BLKCNT_T_DECLARED
#endif
-typedef __cap_rights_t cap_rights_t;
-
#ifndef _CLOCK_T_DECLARED
typedef __clock_t clock_t;
#define _CLOCK_T_DECLARED
@@ -234,6 +232,13 @@ typedef __useconds_t useconds_t; /* microseconds (unsigned) */
#define _USECONDS_T_DECLARED
#endif
+#ifndef _CAP_RIGHTS_T_DECLARED
+#define _CAP_RIGHTS_T_DECLARED
+struct cap_rights;
+
+typedef struct cap_rights cap_rights_t;
+#endif
+
typedef __vm_offset_t vm_offset_t;
typedef __vm_ooffset_t vm_ooffset_t;
typedef __vm_paddr_t vm_paddr_t;
diff --git a/sys/sys/user.h b/sys/sys/user.h
index 9389e55..349003d 100644
--- a/sys/sys/user.h
+++ b/sys/sys/user.h
@@ -61,6 +61,7 @@
#ifndef _SYS_SOCKET_VAR_H_
#include <sys/socket.h>
#endif
+#include <sys/caprights.h>
/*
* KERN_PROC subtype ops return arrays of selected proc structure entries:
@@ -318,7 +319,7 @@ struct kinfo_ofile {
};
#if defined(__amd64__) || defined(__i386__)
-#define KINFO_FILE_SIZE 1392
+#define KINFO_FILE_SIZE 1424
#endif
struct kinfo_file {
@@ -389,6 +390,7 @@ struct kinfo_file {
uint16_t kf_pad1; /* Round to 32 bit alignment. */
int _kf_ispare0; /* Space for more stuff. */
cap_rights_t kf_cap_rights; /* Capability rights. */
+ uint64_t _kf_cap_spare[3]; /* Space for future cap_rights_t. */
int _kf_ispare[4]; /* Space for more stuff. */
/* Truncated before copyout in sysctl */
char kf_path[PATH_MAX]; /* Path to file, if any. */
diff --git a/sys/ufs/ffs/ffs_alloc.c b/sys/ufs/ffs/ffs_alloc.c
index 3063ade..19e880c 100644
--- a/sys/ufs/ffs/ffs_alloc.c
+++ b/sys/ufs/ffs/ffs_alloc.c
@@ -2709,6 +2709,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
long blkcnt, blksize;
struct filedesc *fdp;
struct file *fp, *vfp;
+ cap_rights_t rights;
int filetype, error;
static struct fileops *origops, bufferedops;
@@ -2718,8 +2719,8 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
return (error);
if (cmd.version != FFS_CMD_VERSION)
return (ERPCMISMATCH);
- if ((error = getvnode(td->td_proc->p_fd, cmd.handle, CAP_FSCK,
- &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, cmd.handle,
+ cap_rights_init(&rights, CAP_FSCK), &fp)) != 0)
return (error);
vp = fp->f_data;
if (vp->v_type != VREG && vp->v_type != VDIR) {
@@ -3033,7 +3034,7 @@ sysctl_ffs_fsck(SYSCTL_HANDLER_ARGS)
}
#endif /* DEBUG */
if ((error = getvnode(td->td_proc->p_fd, cmd.value,
- CAP_FSCK, &vfp)) != 0)
+ cap_rights_init(&rights, CAP_FSCK), &vfp)) != 0)
break;
if (vfp->f_vnode->v_type != VCHR) {
fdrop(vfp, td);
diff --git a/sys/vm/vm_mmap.c b/sys/vm/vm_mmap.c
index 53a7be5..77f64f4 100644
--- a/sys/vm/vm_mmap.c
+++ b/sys/vm/vm_mmap.c
@@ -311,17 +311,17 @@ sys_mmap(td, uap)
* rights, but also return the maximum rights to be combined
* with maxprot later.
*/
- rights = CAP_MMAP;
+ cap_rights_init(&rights, CAP_MMAP);
if (prot & PROT_READ)
- rights |= CAP_MMAP_R;
+ cap_rights_set(&rights, CAP_MMAP_R);
if ((flags & MAP_SHARED) != 0) {
if (prot & PROT_WRITE)
- rights |= CAP_MMAP_W;
+ cap_rights_set(&rights, CAP_MMAP_W);
}
if (prot & PROT_EXEC)
- rights |= CAP_MMAP_X;
- if ((error = fget_mmap(td, uap->fd, rights, &cap_maxprot,
- &fp)) != 0)
+ cap_rights_set(&rights, CAP_MMAP_X);
+ error = fget_mmap(td, uap->fd, &rights, &cap_maxprot, &fp);
+ if (error != 0)
goto done;
if (fp->f_type == DTYPE_SHM) {
handle = fp->f_data;
diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
index 06be0c0..0de183c 100644
--- a/usr.bin/kdump/kdump.c
+++ b/usr.bin/kdump/kdump.c
@@ -103,6 +103,7 @@ void ktrcsw_old(struct ktr_csw_old *);
void ktruser_malloc(unsigned char *);
void ktruser_rtld(int, unsigned char *);
void ktruser(int, unsigned char *);
+void ktrcaprights(cap_rights_t *);
void ktrsockaddr(struct sockaddr *);
void ktrstat(struct stat *);
void ktrstruct(char *, size_t);
@@ -379,21 +380,21 @@ limitfd(int fd)
cap_rights_t rights;
unsigned long cmd;
- rights = CAP_FSTAT;
+ cap_rights_init(&rights, CAP_FSTAT);
cmd = -1;
switch (fd) {
case STDIN_FILENO:
- rights |= CAP_READ;
+ cap_rights_set(&rights, CAP_READ);
break;
case STDOUT_FILENO:
- rights |= CAP_IOCTL | CAP_WRITE;
+ cap_rights_set(&rights, CAP_IOCTL, CAP_WRITE);
cmd = TIOCGETA; /* required by isatty(3) in printf(3) */
break;
case STDERR_FILENO:
- rights |= CAP_WRITE;
+ cap_rights_set(&rights, CAP_WRITE);
if (!suppressdata) {
- rights |= CAP_IOCTL;
+ cap_rights_set(&rights, CAP_IOCTL);
cmd = TIOCGWINSZ;
}
break;
@@ -401,7 +402,7 @@ limitfd(int fd)
abort();
}
- if (cap_rights_limit(fd, rights) < 0 && errno != ENOSYS)
+ if (cap_rights_limit(fd, &rights) < 0 && errno != ENOSYS)
err(1, "unable to limit rights for descriptor %d", fd);
if (cmd != -1 && cap_ioctls_limit(fd, &cmd, 1) < 0 && errno != ENOSYS)
err(1, "unable to limit ioctls for descriptor %d", fd);
@@ -1120,35 +1121,6 @@ ktrsyscall(struct ktr_syscall *ktr, u_int flags)
ip++;
narg--;
break;
- case SYS_cap_new:
- case SYS_cap_rights_limit:
- print_number(ip, narg, c);
- putchar(',');
- arg = *ip;
- ip++;
- narg--;
- /*
- * Hack: the second argument is a
- * cap_rights_t, which 64 bits wide, so on
- * 32-bit systems, it is split between two
- * registers.
- *
- * Since sizeof() is not evaluated by the
- * preprocessor, we can't use an #ifdef,
- * but the compiler will probably optimize
- * the code out anyway.
- */
- if (sizeof(cap_rights_t) > sizeof(register_t)) {
-#if _BYTE_ORDER == _LITTLE_ENDIAN
- arg = ((intmax_t)*ip << 32) + arg;
-#else
- arg = (arg << 32) + *ip;
-#endif
- ip++;
- narg--;
- }
- capname(arg);
- break;
case SYS_cap_fcntls_limit:
print_number(ip, narg, c);
putchar(',');
@@ -1536,6 +1508,15 @@ ktruser(int len, unsigned char *p)
}
void
+ktrcaprights(cap_rights_t *rightsp)
+{
+
+ printf("cap_rights_t ");
+ capname(rightsp);
+ printf("\n");
+}
+
+void
ktrsockaddr(struct sockaddr *sa)
{
/*
@@ -1712,6 +1693,7 @@ ktrstruct(char *buf, size_t buflen)
char *name, *data;
size_t namelen, datalen;
int i;
+ cap_rights_t rights;
struct stat sb;
struct sockaddr_storage ss;
@@ -1731,7 +1713,12 @@ ktrstruct(char *buf, size_t buflen)
for (i = 0; i < (int)namelen; ++i)
if (!isalpha(name[i]))
goto invalid;
- if (strcmp(name, "stat") == 0) {
+ if (strcmp(name, "caprights") == 0) {
+ if (datalen != sizeof(cap_rights_t))
+ goto invalid;
+ memcpy(&rights, data, datalen);
+ ktrcaprights(&rights);
+ } else if (strcmp(name, "stat") == 0) {
if (datalen != sizeof(struct stat))
goto invalid;
memcpy(&sb, data, datalen);
@@ -1758,16 +1745,16 @@ ktrcapfail(struct ktr_cap_fail *ktr)
case CAPFAIL_NOTCAPABLE:
/* operation on fd with insufficient capabilities */
printf("operation requires ");
- capname((intmax_t)ktr->cap_needed);
+ capname(&ktr->cap_needed);
printf(", process holds ");
- capname((intmax_t)ktr->cap_held);
+ capname(&ktr->cap_held);
break;
case CAPFAIL_INCREASE:
/* requested more capabilities than fd already has */
printf("attempt to increase capabilities from ");
- capname((intmax_t)ktr->cap_held);
+ capname(&ktr->cap_held);
printf(" to ");
- capname((intmax_t)ktr->cap_needed);
+ capname(&ktr->cap_needed);
break;
case CAPFAIL_SYSCALL:
/* called restricted syscall */
@@ -1779,9 +1766,9 @@ ktrcapfail(struct ktr_cap_fail *ktr)
break;
default:
printf("unknown capability failure: ");
- capname((intmax_t)ktr->cap_needed);
+ capname(&ktr->cap_needed);
printf(" ");
- capname((intmax_t)ktr->cap_held);
+ capname(&ktr->cap_held);
break;
}
printf("\n");
diff --git a/usr.bin/kdump/mksubr b/usr.bin/kdump/mksubr
index b10af94..676e9e2 100644
--- a/usr.bin/kdump/mksubr
+++ b/usr.bin/kdump/mksubr
@@ -385,7 +385,6 @@ _EOF_
auto_or_type "accessmodename" "[A-Z]_OK[[:space:]]+0?x?[0-9A-Fa-f]+" "sys/unistd.h"
auto_switch_type "acltypename" "ACL_TYPE_[A-Z4_]+[[:space:]]+0x[0-9]+" "sys/acl.h"
-auto_or_type "capname" "CAP_[A-Z]+[[:space:]]+0x[01248]{16}ULL" "sys/capability.h"
auto_or_type "capfcntlname" "CAP_FCNTL_[A-Z]+[[:space:]]+\(1" "sys/capability.h"
auto_switch_type "extattrctlname" "EXTATTR_NAMESPACE_[A-Z]+[[:space:]]+0x[0-9]+" "sys/extattr.h"
auto_switch_type "fadvisebehavname" "POSIX_FADV_[A-Z]+[[:space:]]+[0-9]+" "sys/fcntl.h"
@@ -609,3 +608,26 @@ cat <<_EOF_
}
}
}
+
+_EOF_
+egrep '#define[[:space:]]+CAP_[A-Z_]+[[:space:]]+CAPRIGHT\([0-9],[[:space:]]+0x[0-9]{16}ULL\)' \
+ $include_dir/sys/capability.h | \
+ sed -E 's/[ ]+/ /g' | \
+ awk -F '[ \(,\)]' '
+ BEGIN {
+ printf "void\n"
+ printf "capname(const cap_rights_t *rightsp)\n"
+ printf "{\n"
+ printf "\tint comma = 0;\n\n"
+ printf "\tprintf(\"<\");\n"
+ }
+ {
+ printf "\tif ((rightsp->cr_rights[%s] & %s) == %s) {\n", $4, $2, $2
+ printf "\t\tif (comma) printf(\",\"); else comma = 1;\n"
+ printf "\t\tprintf(\"%s\");\n", $2
+ printf "\t}\n"
+ }
+ END {
+ printf "\tprintf(\">\");\n"
+ printf "}\n"
+ }'
diff --git a/usr.bin/procstat/procstat_files.c b/usr.bin/procstat/procstat_files.c
index 72600de..d65c1ae 100644
--- a/usr.bin/procstat/procstat_files.c
+++ b/usr.bin/procstat/procstat_files.c
@@ -133,7 +133,7 @@ print_address(struct sockaddr_storage *ss)
}
static struct cap_desc {
- cap_rights_t cd_right;
+ uint64_t cd_right;
const char *cd_desc;
} cap_desc[] = {
/* General file I/O. */
@@ -244,14 +244,14 @@ static const u_int cap_desc_count = sizeof(cap_desc) /
sizeof(cap_desc[0]);
static u_int
-width_capability(cap_rights_t rights)
+width_capability(cap_rights_t *rightsp)
{
u_int count, i, width;
count = 0;
width = 0;
for (i = 0; i < cap_desc_count; i++) {
- if ((cap_desc[i].cd_right & ~rights) == 0) {
+ if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) {
width += strlen(cap_desc[i].cd_desc);
if (count)
width++;
@@ -262,20 +262,20 @@ width_capability(cap_rights_t rights)
}
static void
-print_capability(cap_rights_t rights, u_int capwidth)
+print_capability(cap_rights_t *rightsp, u_int capwidth)
{
u_int count, i, width;
count = 0;
width = 0;
- for (i = width_capability(rights); i < capwidth; i++) {
- if (rights || i != 0)
+ for (i = width_capability(rightsp); i < capwidth; i++) {
+ if (i != 0)
printf(" ");
else
printf("-");
}
for (i = 0; i < cap_desc_count; i++) {
- if ((cap_desc[i].cd_right & ~rights) == 0) {
+ if (cap_rights_is_set(rightsp, cap_desc[i].cd_right)) {
printf("%s%s", count ? "," : "", cap_desc[i].cd_desc);
width += strlen(cap_desc[i].cd_desc);
if (count)
@@ -306,7 +306,7 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
head = procstat_getfiles(procstat, kipp, 0);
if (head != NULL && Cflag) {
STAILQ_FOREACH(fst, head, next) {
- width = width_capability(fst->fs_cap_rights);
+ width = width_capability(&fst->fs_cap_rights);
if (width > capwidth)
capwidth = width;
}
@@ -460,7 +460,7 @@ procstat_files(struct procstat *procstat, struct kinfo_proc *kipp)
printf("%7c ", '-');
}
if (Cflag) {
- print_capability(fst->fs_cap_rights, capwidth);
+ print_capability(&fst->fs_cap_rights, capwidth);
printf(" ");
}
switch (fst->fs_type) {
diff --git a/usr.bin/rwho/rwho.c b/usr.bin/rwho/rwho.c
index bcb5adb..8c985f0 100644
--- a/usr.bin/rwho/rwho.c
+++ b/usr.bin/rwho/rwho.c
@@ -93,6 +93,7 @@ main(int argc, char *argv[])
struct whod *w;
struct whoent *we;
struct myutmp *mp;
+ cap_rights_t rights;
int f, n, i;
int d_first;
int dfd;
@@ -124,7 +125,8 @@ main(int argc, char *argv[])
err(1, "opendir(%s)", _PATH_RWHODIR);
dfd = dirfd(dirp);
mp = myutmp;
- if (cap_rights_limit(dfd, CAP_READ | CAP_LOOKUP) < 0 && errno != ENOSYS)
+ cap_rights_init(&rights, CAP_READ, CAP_LOOKUP);
+ if (cap_rights_limit(dfd, &rights) < 0 && errno != ENOSYS)
err(1, "cap_rights_limit failed: %s", _PATH_RWHODIR);
/*
* Cache files required for time(3) and localtime(3) before entering
@@ -135,13 +137,14 @@ main(int argc, char *argv[])
if (cap_enter() < 0 && errno != ENOSYS)
err(1, "cap_enter");
(void) time(&now);
+ cap_rights_init(&rights, CAP_READ);
while ((dp = readdir(dirp)) != NULL) {
if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0)
continue;
f = openat(dfd, dp->d_name, O_RDONLY);
if (f < 0)
continue;
- if (cap_rights_limit(f, CAP_READ) < 0 && errno != ENOSYS)
+ if (cap_rights_limit(f, &rights) < 0 && errno != ENOSYS)
err(1, "cap_rights_limit failed: %s", dp->d_name);
cc = read(f, (char *)&wd, sizeof(struct whod));
if (cc < WHDRSIZE) {
diff --git a/usr.bin/uniq/uniq.c b/usr.bin/uniq/uniq.c
index d34b0c0..8e7f40f 100644
--- a/usr.bin/uniq/uniq.c
+++ b/usr.bin/uniq/uniq.c
@@ -145,20 +145,19 @@ main (int argc, char *argv[])
ofp = stdout;
if (argc > 0 && strcmp(argv[0], "-") != 0)
ifp = file(ifn = argv[0], "r");
- if (cap_rights_limit(fileno(ifp), CAP_FSTAT | CAP_READ) < 0 &&
- errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_FSTAT, CAP_READ);
+ if (cap_rights_limit(fileno(ifp), &rights) < 0 && errno != ENOSYS)
err(1, "unable to limit rights for %s", ifn);
- }
- rights = CAP_FSTAT | CAP_WRITE;
+ cap_rights_init(&rights, CAP_FSTAT, CAP_WRITE);
if (argc > 1)
ofp = file(argv[1], "w");
else
- rights |= CAP_IOCTL;
- if (cap_rights_limit(fileno(ofp), rights) < 0 && errno != ENOSYS) {
+ cap_rights_set(&rights, CAP_IOCTL);
+ if (cap_rights_limit(fileno(ofp), &rights) < 0 && errno != ENOSYS) {
err(1, "unable to limit rights for %s",
argc > 1 ? argv[1] : "stdout");
}
- if ((rights & CAP_IOCTL) != 0) {
+ if (cap_rights_is_set(&rights, CAP_IOCTL)) {
unsigned long cmd;
cmd = TIOCGETA; /* required by isatty(3) in printf(3) */
diff --git a/usr.sbin/rwhod/rwhod.c b/usr.sbin/rwhod/rwhod.c
index 25b8692..5dc6079 100644
--- a/usr.sbin/rwhod/rwhod.c
+++ b/usr.sbin/rwhod/rwhod.c
@@ -354,6 +354,7 @@ receiver_process(void)
{
struct sockaddr_in from;
struct stat st;
+ cap_rights_t rights;
char path[64];
int dirfd;
struct whod wd;
@@ -367,8 +368,9 @@ receiver_process(void)
syslog(LOG_WARNING, "%s: %m", _PATH_RWHODIR);
exit(1);
}
- if (cap_rights_limit(dirfd, CAP_CREATE | CAP_WRITE | CAP_FTRUNCATE |
- CAP_SEEK | CAP_LOOKUP | CAP_FSTAT) < 0 && errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_CREATE, CAP_FSTAT, CAP_FTRUNCATE,
+ CAP_LOOKUP, CAP_SEEK, CAP_WRITE);
+ if (cap_rights_limit(dirfd, &rights) < 0 && errno != ENOSYS) {
syslog(LOG_WARNING, "cap_rights_limit: %m");
exit(1);
}
@@ -413,8 +415,8 @@ receiver_process(void)
syslog(LOG_WARNING, "%s: %m", path);
continue;
}
- if (cap_rights_limit(whod, CAP_WRITE | CAP_FTRUNCATE |
- CAP_FSTAT) < 0 && errno != ENOSYS) {
+ cap_rights_init(&rights, CAP_FSTAT, CAP_FTRUNCATE, CAP_WRITE);
+ if (cap_rights_limit(whod, &rights) < 0 && errno != ENOSYS) {
syslog(LOG_WARNING, "cap_rights_limit: %m");
exit(1);
}
OpenPOWER on IntegriCloud