summaryrefslogtreecommitdiffstats
path: root/sys/kern/uipc_syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/uipc_syscalls.c')
-rw-r--r--sys/kern/uipc_syscalls.c35
1 files changed, 21 insertions, 14 deletions
diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c
index 1bcd02e..ae1e203 100644
--- a/sys/kern/uipc_syscalls.c
+++ b/sys/kern/uipc_syscalls.c
@@ -89,20 +89,23 @@ static int sockargs(struct mbuf **, char *, socklen_t, int);
/*
* Convert a user file descriptor to a kernel file entry and check if required
* capability rights are present.
+ * If required copy of current set of capability rights is returned.
* A reference on the file entry is held upon returning.
*/
int
getsock_cap(struct thread *td, int fd, cap_rights_t *rightsp,
- struct file **fpp, u_int *fflagp)
+ struct file **fpp, u_int *fflagp, struct filecaps *havecapsp)
{
struct file *fp;
int error;
- error = fget_unlocked(td->td_proc->p_fd, fd, rightsp, &fp, NULL);
+ error = fget_cap(td, fd, rightsp, &fp, havecapsp);
if (error != 0)
return (error);
if (fp->f_type != DTYPE_SOCKET) {
fdrop(fp, td);
+ if (havecapsp != NULL)
+ filecaps_free(havecapsp);
return (ENOTSOCK);
}
if (fflagp != NULL)
@@ -201,7 +204,7 @@ kern_bindat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
AUDIT_ARG_FD(fd);
AUDIT_ARG_SOCKADDR(td, dirfd, sa);
error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_BIND),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error != 0)
return (error);
so = fp->f_data;
@@ -262,7 +265,7 @@ sys_listen(td, uap)
AUDIT_ARG_FD(uap->s);
error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_LISTEN),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error == 0) {
so = fp->f_data;
#ifdef MAC
@@ -335,6 +338,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name,
struct file *headfp, *nfp = NULL;
struct sockaddr *sa = NULL;
struct socket *head, *so;
+ struct filecaps fcaps;
cap_rights_t rights;
u_int fflag;
pid_t pgid;
@@ -345,7 +349,7 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name,
AUDIT_ARG_FD(s);
error = getsock_cap(td, s, cap_rights_init(&rights, CAP_ACCEPT),
- &headfp, &fflag);
+ &headfp, &fflag, &fcaps);
if (error != 0)
return (error);
head = headfp->f_data;
@@ -358,7 +362,8 @@ kern_accept4(struct thread *td, int s, struct sockaddr **name,
if (error != 0)
goto done;
#endif
- error = falloc(td, &nfp, &fd, (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0);
+ error = falloc_caps(td, &nfp, &fd,
+ (flags & SOCK_CLOEXEC) ? O_CLOEXEC : 0, &fcaps);
if (error != 0)
goto done;
ACCEPT_LOCK();
@@ -467,6 +472,8 @@ noconnection:
* a reference on nfp to the caller on success if they request it.
*/
done:
+ if (nfp == NULL)
+ filecaps_free(&fcaps);
if (fp != NULL) {
if (error == 0) {
*fp = nfp;
@@ -545,7 +552,7 @@ kern_connectat(struct thread *td, int dirfd, int fd, struct sockaddr *sa)
AUDIT_ARG_FD(fd);
AUDIT_ARG_SOCKADDR(td, dirfd, sa);
error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_CONNECT),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error != 0)
return (error);
so = fp->f_data;
@@ -805,7 +812,7 @@ kern_sendit(td, s, mp, flags, control, segflg)
AUDIT_ARG_SOCKADDR(td, AT_FDCWD, mp->msg_name);
cap_rights_set(&rights, CAP_CONNECT);
}
- error = getsock_cap(td, s, &rights, &fp, NULL);
+ error = getsock_cap(td, s, &rights, &fp, NULL, NULL);
if (error != 0) {
m_freem(control);
return (error);
@@ -1013,7 +1020,7 @@ kern_recvit(td, s, mp, fromseg, controlp)
AUDIT_ARG_FD(s);
error = getsock_cap(td, s, cap_rights_init(&rights, CAP_RECV),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error != 0)
return (error);
so = fp->f_data;
@@ -1328,7 +1335,7 @@ sys_shutdown(td, uap)
AUDIT_ARG_FD(uap->s);
error = getsock_cap(td, uap->s, cap_rights_init(&rights, CAP_SHUTDOWN),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error == 0) {
so = fp->f_data;
error = soshutdown(so, uap->how);
@@ -1402,7 +1409,7 @@ kern_setsockopt(td, s, level, name, val, valseg, valsize)
AUDIT_ARG_FD(s);
error = getsock_cap(td, s, cap_rights_init(&rights, CAP_SETSOCKOPT),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error == 0) {
so = fp->f_data;
error = sosetopt(so, &sopt);
@@ -1483,7 +1490,7 @@ kern_getsockopt(td, s, level, name, val, valseg, valsize)
AUDIT_ARG_FD(s);
error = getsock_cap(td, s, cap_rights_init(&rights, CAP_GETSOCKOPT),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error == 0) {
so = fp->f_data;
error = sogetopt(so, &sopt);
@@ -1544,7 +1551,7 @@ kern_getsockname(struct thread *td, int fd, struct sockaddr **sa,
AUDIT_ARG_FD(fd);
error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETSOCKNAME),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error != 0)
return (error);
so = fp->f_data;
@@ -1643,7 +1650,7 @@ kern_getpeername(struct thread *td, int fd, struct sockaddr **sa,
AUDIT_ARG_FD(fd);
error = getsock_cap(td, fd, cap_rights_init(&rights, CAP_GETPEERNAME),
- &fp, NULL);
+ &fp, NULL, NULL);
if (error != 0)
return (error);
so = fp->f_data;
OpenPOWER on IntegriCloud