diff options
author | maxim <maxim@FreeBSD.org> | 2006-06-13 14:33:35 +0000 |
---|---|---|
committer | maxim <maxim@FreeBSD.org> | 2006-06-13 14:33:35 +0000 |
commit | 0cf435f0166917eec5064b5dafbccc3b2dbb0dca (patch) | |
tree | ec8960703a0411659c348210afac8d097376e705 /sys | |
parent | 033f8e47d2aba2ec3d03076f1b808cb3407eef2f (diff) | |
download | FreeBSD-src-0cf435f0166917eec5064b5dafbccc3b2dbb0dca.zip FreeBSD-src-0cf435f0166917eec5064b5dafbccc3b2dbb0dca.tar.gz |
o There are two methods to get a process credentials over the unix
sockets:
1) A sender sends SCM_CREDS message to a reciever, struct cmsgcred;
2) A reciever sets LOCAL_CREDS socket option and gets sender
credentials in control message, struct sockcred.
Both methods use the same control message type SCM_CREDS with the
same control message level SOL_SOCKET, so they are indistinguishable
for the receiver. A difference in struct cmsgcred and struct sockcred
layouts may lead to unwanted effects.
Now for sockets with LOCAL_CREDS option remove all previous linked
SCM_CREDS control messages and then add a control message with
struct sockcred so the process specifically asked for the peer
credentials by LOCAL_CREDS option always gets struct sockcred.
PR: kern/90800
Submitted by: Andrey Simonenko
Regres. tests: tools/regression/sockets/unix_cmsg/
MFC after: 1 month
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/uipc_usrreq.c | 36 |
1 files changed, 25 insertions, 11 deletions
diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c index c6893b9..f16d7b7 100644 --- a/sys/kern/uipc_usrreq.c +++ b/sys/kern/uipc_usrreq.c @@ -1498,8 +1498,9 @@ out: struct mbuf * unp_addsockcred(struct thread *td, struct mbuf *control) { - struct mbuf *m, *n; + struct mbuf *m, *n, *n_prev; struct sockcred *sc; + const struct cmsghdr *cm; int ngroups; int i; @@ -1508,7 +1509,6 @@ unp_addsockcred(struct thread *td, struct mbuf *control) m = sbcreatecontrol(NULL, SOCKCREDSIZE(ngroups), SCM_CREDS, SOL_SOCKET); if (m == NULL) return (control); - m->m_next = NULL; sc = (struct sockcred *) CMSG_DATA(mtod(m, struct cmsghdr *)); sc->sc_uid = td->td_ucred->cr_ruid; @@ -1520,16 +1520,30 @@ unp_addsockcred(struct thread *td, struct mbuf *control) sc->sc_groups[i] = td->td_ucred->cr_groups[i]; /* - * If a control message already exists, append us to the end. + * Unlink SCM_CREDS control messages (struct cmsgcred), since + * just created SCM_CREDS control message (struct sockcred) has + * another format. */ - if (control != NULL) { - for (n = control; n->m_next != NULL; n = n->m_next) - ; - n->m_next = m; - } else - control = m; - - return (control); + if (control != NULL) + for (n = control, n_prev = NULL; n != NULL;) { + cm = mtod(n, struct cmsghdr *); + if (cm->cmsg_level == SOL_SOCKET && + cm->cmsg_type == SCM_CREDS) { + if (n_prev == NULL) + control = n->m_next; + else + n_prev->m_next = n->m_next; + n = m_free(n); + } else { + n_prev = n; + n = n->m_next; + } + } + + /* Prepend it to the head. */ + m->m_next = control; + + return (m); } /* |