FreeBSD Bugzilla – Attachment 108351 Details for
Bug 149168
[linux] [patch] Linux sendmsg / recvmsg / etc fixes for pulseaudio
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
file.diff
file.diff (text/plain), 10.92 KB, created by
john
on 2010-08-01 05:30:04 UTC
(
hide
)
Description:
file.diff
Filename:
MIME Type:
Creator:
john
Created:
2010-08-01 05:30:04 UTC
Size:
10.92 KB
patch
obsolete
>--- ./compat/linux/linux_misc.h.ORIGINAL 2010-06-13 22:09:06.000000000 -0400 >+++ ./compat/linux/linux_misc.h 2010-07-31 23:33:18.000000000 -0400 >@@ -37,6 +37,8 @@ > * Second arg is a ptr to return the > * signal. > */ >+#define LINUX_PR_GET_KEEPCAPS 7 /* Get drop capabilities on setuid */ >+#define LINUX_PR_SET_KEEPCAPS 8 /* Set drop capabilities on setuid */ > #define LINUX_PR_SET_NAME 15 /* Set process name. */ > #define LINUX_PR_GET_NAME 16 /* Get process name. */ > >--- ./compat/linux/linux_misc.c.ORIGINAL 2010-06-13 22:09:06.000000000 -0400 >+++ ./compat/linux/linux_misc.c 2010-07-31 00:09:16.000000000 -0400 >@@ -1733,6 +1733,87 @@ linux_exit_group(struct thread *td, stru > return (0); > } > >+#define _LINUX_CAPABILITY_VERSION 0x19980330 >+ >+struct l_user_cap_header { >+ l_int version; >+ l_int pid; >+}; >+ >+struct l_user_cap_data { >+ l_int effective; >+ l_int permitted; >+ l_int inheritable; >+}; >+ >+int >+linux_capget(struct thread *td, struct linux_capget_args *args) >+{ >+ struct l_user_cap_header luch; >+ struct l_user_cap_data lucd; >+ int error; >+ >+ if (! args->hdrp) >+ return (EFAULT); >+ >+ error = copyin(args->hdrp, &luch, sizeof(luch)); >+ if (error != 0) >+ return (error); >+ >+ if (luch.version != _LINUX_CAPABILITY_VERSION) { >+ luch.version = _LINUX_CAPABILITY_VERSION; >+ error = copyout(&luch, args->hdrp, sizeof(luch)); >+ if (error) >+ return (error); >+ return (EINVAL); >+ } >+ >+ if (luch.pid) >+ return (EPERM); >+ >+ if (args->datap) { >+ bzero (&lucd, sizeof(lucd)); >+ error = copyout(&lucd, args->datap, sizeof(lucd)); >+ } >+ >+ return (error); >+} >+ >+int >+linux_capset(struct thread *td, struct linux_capset_args *args) >+{ >+ struct l_user_cap_header luch; >+ struct l_user_cap_data lucd; >+ int error; >+ >+ if (! args->hdrp || ! args->datap) >+ return (EFAULT); >+ >+ error = copyin(args->hdrp, &luch, sizeof(luch)); >+ if (error != 0) >+ return (error); >+ >+ if (luch.version != _LINUX_CAPABILITY_VERSION) { >+ luch.version = _LINUX_CAPABILITY_VERSION; >+ error = copyout(&luch, args->hdrp, sizeof(luch)); >+ if (error) >+ return (error); >+ return (EINVAL); >+ } >+ >+ if (luch.pid) >+ return (EPERM); >+ >+ error = copyin(args->datap, &lucd, sizeof(lucd)); >+ if (error != 0) >+ return (error); >+ >+ if (lucd.effective || lucd.permitted || lucd.inheritable) >+ return (EPERM); >+ >+ return (0); >+} >+ > int > linux_prctl(struct thread *td, struct linux_prctl_args *args) > { >@@ -1766,6 +1847,11 @@ linux_prctl(struct thread *td, struct li > (void *)(register_t)args->arg2, > sizeof(pdeath_signal)); > break; >+ case LINUX_PR_GET_KEEPCAPS: >+ td->td_retval[0] = 0; >+ break; >+ case LINUX_PR_SET_KEEPCAPS: >+ break; > case LINUX_PR_SET_NAME: > /* > * To be on the safe side we need to make sure to not >--- ./compat/linux/linux_socket.h.ORIGINAL 2010-06-13 22:09:06.000000000 -0400 >+++ ./compat/linux/linux_socket.h 2010-07-28 23:44:10.000000000 -0400 >@@ -53,6 +53,7 @@ > /* Socket-level control message types */ > > #define LINUX_SCM_RIGHTS 0x01 >+#define LINUX_SCM_CREDENTIALS 0x02 > > /* Ancilliary data object information macros */ > >--- ./compat/linux/linux_socket.c.ORIGINAL 2010-07-28 23:45:26.000000000 -0400 >+++ ./compat/linux/linux_socket.c 2010-07-31 23:56:08.000000000 -0400 >@@ -433,6 +433,8 @@ linux_to_bsd_cmsg_type(int cmsg_type) > switch (cmsg_type) { > case LINUX_SCM_RIGHTS: > return (SCM_RIGHTS); >+ case LINUX_SCM_CREDENTIALS: >+ return (SCM_CREDS); > } > return (-1); > } >@@ -444,6 +446,8 @@ bsd_to_linux_cmsg_type(int cmsg_type) > switch (cmsg_type) { > case SCM_RIGHTS: > return (LINUX_SCM_RIGHTS); >+ case SCM_CREDS: >+ return (LINUX_SCM_CREDENTIALS); > } > return (-1); > } >@@ -472,7 +476,7 @@ bsd_to_linux_msghdr(const struct msghdr > lhdr->msg_iov = PTROUT(bhdr->msg_iov); > lhdr->msg_iovlen = bhdr->msg_iovlen; > lhdr->msg_control = PTROUT(bhdr->msg_control); >- lhdr->msg_controllen = bhdr->msg_controllen; >+ /* msg_controllen skipped */ > /* msg_flags skipped */ > return (0); > } >@@ -1092,6 +1096,7 @@ static int > linux_sendmsg(struct thread *td, struct linux_sendmsg_args *args) > { > struct cmsghdr *cmsg; >+ struct cmsgcred cmcred; > struct mbuf *control; > struct msghdr msg; > struct l_cmsghdr linux_cmsg; >@@ -1099,6 +1104,8 @@ linux_sendmsg(struct thread *td, struct > struct l_msghdr linux_msg; > struct iovec *iov; > socklen_t datalen; >+ struct sockaddr *sa; >+ sa_family_t sa_family; > void *data; > int error; > >@@ -1128,7 +1135,16 @@ linux_sendmsg(struct thread *td, struct > if (error) > return (error); > >+ control = NULL; >+ cmsg = NULL; >+ > if (msg.msg_control != NULL) { >+ error = kern_getsockname(td, args->s, &sa, &datalen); >+ if (error) >+ goto bad; >+ sa_family = sa->sa_family; >+ free(sa, M_SONAME); >+ > error = ENOBUFS; > cmsg = malloc(CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO); > control = m_get(M_WAIT, MT_CONTROL); >@@ -1147,18 +1163,46 @@ linux_sendmsg(struct thread *td, struct > goto bad; > > /* >- * Now we support only SCM_RIGHTS, so return EINVAL >- * in any other cmsg_type >+ * Now we support only SCM_RIGHTS and SCM_CRED, >+ * so return EINVAL in any other cmsg_type > */ >- if ((cmsg->cmsg_type = >- linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type)) == -1) >- goto bad; >+ cmsg->cmsg_type = >+ linux_to_bsd_cmsg_type(linux_cmsg.cmsg_type); > cmsg->cmsg_level = > linux_to_bsd_sockopt_level(linux_cmsg.cmsg_level); >+ if (cmsg->cmsg_type == -1 >+ || cmsg->cmsg_level != SOL_SOCKET) >+ goto bad; >+ >+ /* >+ * Some applications (e.g. pulseaudio) attempt to >+ * send ancillary data even if the underlying protocol >+ * doesn't support it which is not allowed in the >+ * FreeBSD system call interface. >+ */ >+ if (sa_family != AF_UNIX) >+ continue; > >+ data = LINUX_CMSG_DATA(ptr_cmsg); > datalen = linux_cmsg.cmsg_len - L_CMSG_HDRSZ; >+ >+ switch (cmsg->cmsg_type) >+ { >+ case SCM_RIGHTS: >+ break; >+ >+ case SCM_CREDS: >+ data = &cmcred; >+ datalen = sizeof(cmcred); >+ >+ /* >+ * The lower levels will fill in the structure >+ */ >+ bzero(data, datalen); >+ break; >+ } >+ > cmsg->cmsg_len = CMSG_LEN(datalen); >- data = LINUX_CMSG_DATA(ptr_cmsg); > > error = ENOBUFS; > if (!m_append(control, CMSG_HDRSZ, (c_caddr_t) cmsg)) >@@ -1166,9 +1210,11 @@ linux_sendmsg(struct thread *td, struct > if (!m_append(control, datalen, (c_caddr_t) data)) > goto bad; > } while ((ptr_cmsg = LINUX_CMSG_NXTHDR(&msg, ptr_cmsg))); >- } else { >- control = NULL; >- cmsg = NULL; >+ >+ if (m_length(control, NULL) == 0) { >+ m_freem(control); >+ control = NULL; >+ } > } > > msg.msg_iov = iov; >@@ -1193,9 +1239,11 @@ static int > linux_recvmsg(struct thread *td, struct linux_recvmsg_args *args) > { > struct cmsghdr *cm; >+ struct cmsgcred *cmcred; > struct msghdr msg; > struct l_cmsghdr *linux_cmsg = NULL; >- socklen_t datalen, outlen, clen; >+ struct l_ucred linux_ucred; >+ socklen_t datalen, outlen; > struct l_msghdr linux_msg; > struct iovec *iov, *uiov; > struct mbuf *control = NULL; >@@ -1252,39 +1300,35 @@ linux_recvmsg(struct thread *td, struct > goto bad; > } > >- if (control) { >+ outbuf = PTRIN(linux_msg.msg_control); >+ outlen = 0; > >+ if (control) { > linux_cmsg = malloc(L_CMSG_HDRSZ, M_TEMP, M_WAITOK | M_ZERO); >- outbuf = PTRIN(linux_msg.msg_control); >- cm = mtod(control, struct cmsghdr *); >- outlen = 0; >- clen = control->m_len; > >- while (cm != NULL) { >+ msg.msg_control = mtod(control, struct cmsghdr *); >+ msg.msg_controllen = control->m_len; >+ >+ cm = CMSG_FIRSTHDR(&msg); > >- if ((linux_cmsg->cmsg_type = >- bsd_to_linux_cmsg_type(cm->cmsg_type)) == -1) >+ while (cm != NULL) { >+ linux_cmsg->cmsg_type = >+ bsd_to_linux_cmsg_type(cm->cmsg_type); >+ linux_cmsg->cmsg_level = >+ bsd_to_linux_sockopt_level(cm->cmsg_level); >+ if (linux_cmsg->cmsg_type == -1 >+ || cm->cmsg_level != SOL_SOCKET) > { > error = EINVAL; > goto bad; > } >+ > data = CMSG_DATA(cm); > datalen = (caddr_t)cm + cm->cmsg_len - (caddr_t)data; > >- switch (linux_cmsg->cmsg_type) >+ switch (cm->cmsg_type) > { >- case LINUX_SCM_RIGHTS: >- if (outlen + LINUX_CMSG_LEN(datalen) > >- linux_msg.msg_controllen) { >- if (outlen == 0) { >- error = EMSGSIZE; >- goto bad; >- } else { >- linux_msg.msg_flags |= >- LINUX_MSG_CTRUNC; >- goto out; >- } >- } >+ case SCM_RIGHTS: > if (args->flags & LINUX_MSG_CMSG_CLOEXEC) { > fds = datalen / sizeof(int); > fdp = data; >@@ -1295,11 +1339,40 @@ linux_recvmsg(struct thread *td, struct > } > } > break; >+ >+ case SCM_CREDS: >+ /* >+ * Currently LOCAL_CREDS is never in >+ * effect for Linux so no need to worry >+ * about sockcred >+ */ >+ if (datalen != sizeof (*cmcred)) { >+ error = EMSGSIZE; >+ goto bad; >+ } >+ cmcred = (struct cmsgcred *)data; >+ bzero(&linux_ucred, sizeof(linux_ucred)); >+ linux_ucred.pid = cmcred->cmcred_pid; >+ linux_ucred.uid = cmcred->cmcred_uid; >+ linux_ucred.gid = cmcred->cmcred_gid; >+ data = &linux_ucred; >+ datalen = sizeof(linux_ucred); >+ break; >+ } >+ >+ if (outlen + LINUX_CMSG_LEN(datalen) > >+ linux_msg.msg_controllen) { >+ if (outlen == 0) { >+ error = EMSGSIZE; >+ goto bad; >+ } else { >+ linux_msg.msg_flags |= >+ LINUX_MSG_CTRUNC; >+ goto out; >+ } > } > > linux_cmsg->cmsg_len = LINUX_CMSG_LEN(datalen); >- linux_cmsg->cmsg_level = >- bsd_to_linux_sockopt_level(cm->cmsg_level); > > error = copyout(linux_cmsg, outbuf, L_CMSG_HDRSZ); > if (error) >@@ -1312,18 +1385,13 @@ linux_recvmsg(struct thread *td, struct > > outbuf += LINUX_CMSG_ALIGN(datalen); > outlen += LINUX_CMSG_LEN(datalen); >- linux_msg.msg_controllen = outlen; > >- if (CMSG_SPACE(datalen) < clen) { >- clen -= CMSG_SPACE(datalen); >- cm = (struct cmsghdr *) >- ((caddr_t)cm + CMSG_SPACE(datalen)); >- } else >- cm = NULL; >+ cm = CMSG_NXTHDR(&msg, cm); > } > } > > out: >+ linux_msg.msg_controllen = outlen; > error = copyout(&linux_msg, PTRIN(args->msg), sizeof(linux_msg)); > > bad: >--- ./i386/linux/linux_proto.h.ORIGINAL 2010-06-13 22:09:06.000000000 -0400 >+++ ./i386/linux/linux_proto.h 2010-07-30 23:33:15.000000000 -0400 >@@ -586,10 +586,12 @@ struct linux_getcwd_args { > char bufsize_l_[PADL_(l_ulong)]; l_ulong bufsize; char bufsize_r_[PADR_(l_ulong)]; > }; > struct linux_capget_args { >- register_t dummy; >+ char hdrp_l_[PADL_(void *)]; void * hdrp; char hdrp_r_[PADR_(void *)]; >+ char datap_l_[PADL_(void *)]; void * datap; char datap_r_[PADR_(void *)]; > }; > struct linux_capset_args { >- register_t dummy; >+ char hdrp_l_[PADL_(void *)]; void * hdrp; char hdrp_r_[PADR_(void *)]; >+ char datap_l_[PADL_(void *)]; void * datap; char datap_r_[PADR_(void *)]; > }; > struct linux_sigaltstack_args { > char uss_l_[PADL_(l_stack_t *)]; l_stack_t * uss; char uss_r_[PADR_(l_stack_t *)]; >--- ./i386/linux/linux_dummy.c.ORIGINAL 2010-06-13 22:09:06.000000000 -0400 >+++ ./i386/linux/linux_dummy.c 2010-07-30 23:33:46.000000000 -0400 >@@ -57,8 +57,6 @@ DUMMY(vm86); > DUMMY(query_module); > DUMMY(nfsservctl); > DUMMY(rt_sigqueueinfo); >-DUMMY(capget); >-DUMMY(capset); > DUMMY(sendfile); /* different semantics */ > DUMMY(setfsuid); > DUMMY(setfsgid);
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 149168
: 108351