summaryrefslogtreecommitdiffstats
path: root/sys/compat
diff options
context:
space:
mode:
authorpjd <pjd@FreeBSD.org>2013-03-02 00:53:12 +0000
committerpjd <pjd@FreeBSD.org>2013-03-02 00:53:12 +0000
commitf07ebb8888ea42f744890a727e8f6799a1086915 (patch)
tree90495ae13fcc0dd621d97fc1b788f43780023c0a /sys/compat
parentdd15932a159ec60641cd20e4fb689fa28d75465d (diff)
downloadFreeBSD-src-f07ebb8888ea42f744890a727e8f6799a1086915.zip
FreeBSD-src-f07ebb8888ea42f744890a727e8f6799a1086915.tar.gz
Merge Capsicum overhaul:
- Capability is no longer separate descriptor type. Now every descriptor has set of its own capability rights. - The cap_new(2) system call is left, but it is no longer documented and should not be used in new code. - The new syscall cap_rights_limit(2) should be used instead of cap_new(2), which limits capability rights of the given descriptor without creating a new one. - The cap_getrights(2) syscall is renamed to cap_rights_get(2). - If CAP_IOCTL capability right is present we can further reduce allowed ioctls list with the new cap_ioctls_limit(2) syscall. List of allowed ioctls can be retrived with cap_ioctls_get(2) syscall. - If CAP_FCNTL capability right is present we can further reduce fcntls that can be used with the new cap_fcntls_limit(2) syscall and retrive them with cap_fcntls_get(2). - To support ioctl and fcntl white-listing the filedesc structure was heavly modified. - The audit subsystem, kdump and procstat tools were updated to recognize new syscalls. - Capability rights were revised and eventhough I tried hard to provide backward API and ABI compatibility there are some incompatible changes that are described in detail below: CAP_CREATE old behaviour: - Allow for openat(2)+O_CREAT. - Allow for linkat(2). - Allow for symlinkat(2). CAP_CREATE new behaviour: - Allow for openat(2)+O_CREAT. Added CAP_LINKAT: - Allow for linkat(2). ABI: Reuses CAP_RMDIR bit. - Allow to be target for renameat(2). Added CAP_SYMLINKAT: - Allow for symlinkat(2). Removed CAP_DELETE. Old behaviour: - Allow for unlinkat(2) when removing non-directory object. - Allow to be source for renameat(2). Removed CAP_RMDIR. Old behaviour: - Allow for unlinkat(2) when removing directory. Added CAP_RENAMEAT: - Required for source directory for the renameat(2) syscall. Added CAP_UNLINKAT (effectively it replaces CAP_DELETE and CAP_RMDIR): - Allow for unlinkat(2) on any object. - Required if target of renameat(2) exists and will be removed by this call. Removed CAP_MAPEXEC. CAP_MMAP old behaviour: - Allow for mmap(2) with any combination of PROT_NONE, PROT_READ and PROT_WRITE. CAP_MMAP new behaviour: - Allow for mmap(2)+PROT_NONE. Added CAP_MMAP_R: - Allow for mmap(PROT_READ). Added CAP_MMAP_W: - Allow for mmap(PROT_WRITE). Added CAP_MMAP_X: - Allow for mmap(PROT_EXEC). Added CAP_MMAP_RW: - Allow for mmap(PROT_READ | PROT_WRITE). Added CAP_MMAP_RX: - Allow for mmap(PROT_READ | PROT_EXEC). Added CAP_MMAP_WX: - Allow for mmap(PROT_WRITE | PROT_EXEC). Added CAP_MMAP_RWX: - Allow for mmap(PROT_READ | PROT_WRITE | PROT_EXEC). Renamed CAP_MKDIR to CAP_MKDIRAT. Renamed CAP_MKFIFO to CAP_MKFIFOAT. Renamed CAP_MKNODE to CAP_MKNODEAT. CAP_READ old behaviour: - Allow pread(2). - Disallow read(2), readv(2) (if there is no CAP_SEEK). CAP_READ new behaviour: - Allow read(2), readv(2). - Disallow pread(2) (CAP_SEEK was also required). CAP_WRITE old behaviour: - Allow pwrite(2). - Disallow write(2), writev(2) (if there is no CAP_SEEK). CAP_WRITE new behaviour: - Allow write(2), writev(2). - Disallow pwrite(2) (CAP_SEEK was also required). Added convinient defines: #define CAP_PREAD (CAP_SEEK | CAP_READ) #define CAP_PWRITE (CAP_SEEK | CAP_WRITE) #define CAP_MMAP_R (CAP_MMAP | CAP_SEEK | CAP_READ) #define CAP_MMAP_W (CAP_MMAP | CAP_SEEK | CAP_WRITE) #define CAP_MMAP_X (CAP_MMAP | CAP_SEEK | 0x0000000000000008ULL) #define CAP_MMAP_RW (CAP_MMAP_R | CAP_MMAP_W) #define CAP_MMAP_RX (CAP_MMAP_R | CAP_MMAP_X) #define CAP_MMAP_WX (CAP_MMAP_W | CAP_MMAP_X) #define CAP_MMAP_RWX (CAP_MMAP_R | CAP_MMAP_W | CAP_MMAP_X) #define CAP_RECV CAP_READ #define CAP_SEND CAP_WRITE #define CAP_SOCK_CLIENT \ (CAP_CONNECT | CAP_GETPEERNAME | CAP_GETSOCKNAME | CAP_GETSOCKOPT | \ CAP_PEELOFF | CAP_RECV | CAP_SEND | CAP_SETSOCKOPT | CAP_SHUTDOWN) #define CAP_SOCK_SERVER \ (CAP_ACCEPT | CAP_BIND | CAP_GETPEERNAME | CAP_GETSOCKNAME | \ CAP_GETSOCKOPT | CAP_LISTEN | CAP_PEELOFF | CAP_RECV | CAP_SEND | \ CAP_SETSOCKOPT | CAP_SHUTDOWN) Added defines for backward API compatibility: #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) Sponsored by: The FreeBSD Foundation Reviewed by: Christoph Mallon <christoph.mallon@gmx.de> Many aspects discussed with: rwatson, benl, jonathan ABI compatibility discussed with: kib
Diffstat (limited to 'sys/compat')
-rw-r--r--sys/compat/freebsd32/syscalls.master12
-rw-r--r--sys/compat/linux/linux_file.c9
-rw-r--r--sys/compat/svr4/svr4_fcntl.c6
-rw-r--r--sys/compat/svr4/svr4_filio.c10
-rw-r--r--sys/compat/svr4/svr4_misc.c7
-rw-r--r--sys/compat/svr4/svr4_stream.c4
6 files changed, 29 insertions, 19 deletions
diff --git a/sys/compat/freebsd32/syscalls.master b/sys/compat/freebsd32/syscalls.master
index 4106447..6552d13 100644
--- a/sys/compat/freebsd32/syscalls.master
+++ b/sys/compat/freebsd32/syscalls.master
@@ -963,7 +963,7 @@
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_GETRIGHTS NOPROTO { int cap_getrights(int fd, \
+515 AUE_CAP_RIGHTS_GET NOPROTO { int cap_rights_get(int fd, \
uint64_t *rightsp); }
516 AUE_CAP_ENTER NOPROTO { int cap_enter(void); }
517 AUE_CAP_GETMODE NOPROTO { int cap_getmode(u_int *modep); }
@@ -1005,3 +1005,13 @@
struct wrusage32 *wrusage, \
siginfo_t *info); }
+533 AUE_CAP_RIGHTS_LIMIT NOPROTO { int cap_rights_limit(int fd, \
+ uint64_t rights); }
+534 AUE_CAP_IOCTLS_LIMIT NOPROTO { int cap_ioctls_limit(int fd, \
+ const u_long *cmds, size_t ncmds); }
+535 AUE_CAP_IOCTLS_GET NOPROTO { ssize_t cap_ioctls_get(int fd, \
+ u_long *cmds, size_t maxcmds); }
+536 AUE_CAP_FCNTLS_LIMIT NOPROTO { int cap_fcntls_limit(int fd, \
+ uint32_t fcntlrights); }
+537 AUE_CAP_FCNTLS_GET NOPROTO { int cap_fcntls_get(int fd, \
+ uint32_t *fcntlrightsp); }
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 0318a5c..346d178 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -154,6 +154,7 @@ linux_common_open(struct thread *td, int dirfd, char *path, int l_flags, int mod
SESS_LEADER(p) && !(p->p_flag & P_CONTROLT)) {
PROC_UNLOCK(p);
sx_unlock(&proctree_lock);
+ /* XXXPJD: Verify if TIOCSCTTY is allowed. */
if (fp->f_type == DTYPE_VNODE)
(void) fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0,
td->td_ucred, td);
@@ -1038,11 +1039,11 @@ linux_pread(td, uap)
error = sys_pread(td, &bsd);
if (error == 0) {
- /* This seems to violate POSIX but linux does it */
- if ((error = fgetvp(td, uap->fd, CAP_READ, &vp)) != 0)
- return (error);
+ /* This seems to violate POSIX but linux does it */
+ if ((error = fgetvp(td, uap->fd, CAP_PREAD, &vp)) != 0)
+ return (error);
if (vp->v_type == VDIR) {
- vrele(vp);
+ vrele(vp);
return (EISDIR);
}
vrele(vp);
diff --git a/sys/compat/svr4/svr4_fcntl.c b/sys/compat/svr4/svr4_fcntl.c
index b9d3ace..86fab78 100644
--- a/sys/compat/svr4/svr4_fcntl.c
+++ b/sys/compat/svr4/svr4_fcntl.c
@@ -265,14 +265,14 @@ fd_revoke(td, fd)
/*
* If we ever want to support Capsicum on SVR4 processes (unlikely)
* or FreeBSD grows a native frevoke() (more likely), we will need a
- * CAP_REVOKE here.
+ * CAP_FREVOKE here.
*
- * In the meantime, use CAP_MASK_VALID: 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_MASK_VALID, &vp)) != 0)
+ if ((error = fgetvp(td, fd, CAP_ALL, &vp)) != 0)
return (error);
if (vp->v_type != VCHR && vp->v_type != VBLK) {
diff --git a/sys/compat/svr4/svr4_filio.c b/sys/compat/svr4/svr4_filio.c
index 967169b..0fbba07 100644
--- a/sys/compat/svr4/svr4_filio.c
+++ b/sys/compat/svr4/svr4_filio.c
@@ -197,22 +197,24 @@ svr4_fil_ioctl(fp, td, retval, fd, cmd, data)
u_long cmd;
caddr_t data;
{
- int error;
- int num;
struct filedesc *fdp = td->td_proc->p_fd;
+ struct filedescent *fde;
+ int error, num;
*retval = 0;
switch (cmd) {
case SVR4_FIOCLEX:
FILEDESC_XLOCK(fdp);
- fdp->fd_ofileflags[fd] |= UF_EXCLOSE;
+ fde = &fdp->fd_ofiles[fd];
+ fde->fde_flags |= UF_EXCLOSE;
FILEDESC_XUNLOCK(fdp);
return 0;
case SVR4_FIONCLEX:
FILEDESC_XLOCK(fdp);
- fdp->fd_ofileflags[fd] &= ~UF_EXCLOSE;
+ fde = &fdp->fd_ofiles[fd];
+ fde->fde_flags &= ~UF_EXCLOSE;
FILEDESC_XUNLOCK(fdp);
return 0;
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index d6bc4eb..0cfaeae 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -247,10 +247,8 @@ 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 | CAP_SEEK, &fp)) != 0) {
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 0)
return (error);
- }
if ((fp->f_flag & FREAD) == 0) {
fdrop(fp, td);
@@ -426,8 +424,7 @@ svr4_sys_getdents(td, uap)
if (uap->nbytes < 0)
return (EINVAL);
- if ((error = getvnode(td->td_proc->p_fd, uap->fd,
- CAP_READ | CAP_SEEK, &fp)) != 0)
+ if ((error = getvnode(td->td_proc->p_fd, uap->fd, CAP_READ, &fp)) != 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 27014e3..1c7e83e 100644
--- a/sys/compat/svr4/svr4_stream.c
+++ b/sys/compat/svr4/svr4_stream.c
@@ -1449,7 +1449,7 @@ svr4_sys_putmsg(td, uap)
struct file *fp;
int error;
- if ((error = fget(td, uap->fd, CAP_WRITE, &fp)) != 0) {
+ if ((error = fget(td, uap->fd, CAP_SEND, &fp)) != 0) {
#ifdef DEBUG_SVR4
uprintf("putmsg: bad fp\n");
#endif
@@ -1621,7 +1621,7 @@ svr4_sys_getmsg(td, uap)
struct file *fp;
int error;
- if ((error = fget(td, uap->fd, CAP_READ, &fp)) != 0) {
+ if ((error = fget(td, uap->fd, CAP_RECV, &fp)) != 0) {
#ifdef DEBUG_SVR4
uprintf("getmsg: bad fp\n");
#endif
OpenPOWER on IntegriCloud