diff --git a/include/net/scm.h b/include/net/scm.h index 745460f..68e1e48 100644 --- a/include/net/scm.h +++ b/include/net/scm.h @@ -53,6 +53,14 @@ static __inline__ void scm_set_cred(struct scm_cookie *scm, cred_to_ucred(pid, cred, &scm->creds); } +static __inline__ void scm_set_cred_noref(struct scm_cookie *scm, + struct pid *pid, const struct cred *cred) +{ + scm->pid = pid; + scm->cred = cred; + cred_to_ucred(pid, cred, &scm->creds); +} + static __inline__ void scm_destroy_cred(struct scm_cookie *scm) { put_pid(scm->pid); @@ -108,15 +125,14 @@ static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg, if (!msg->msg_control) { if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp) msg->msg_flags |= MSG_CTRUNC; - scm_destroy(scm); + if (scm && scm->fp) + __scm_destroy(scm); return; } if (test_bit(SOCK_PASSCRED, &sock->flags)) put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds); - scm_destroy_cred(scm); - scm_passec(sock, msg, scm); if (!scm->fp) diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index ec68e1c..e6d9d10 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c @@ -1777,7 +1789,7 @@ static int unix_dgram_recvmsg(struct kiocb *iocb, struct socket *sock, siocb->scm = &tmp_scm; memset(&tmp_scm, 0, sizeof(tmp_scm)); } - scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); + scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); unix_set_secdata(siocb->scm, skb); if (!(flags & MSG_PEEK)) { @@ -1939,7 +1951,8 @@ static int unix_stream_recvmsg(struct kiocb *iocb, struct socket *sock, } } else { /* Copy credentials */ - scm_set_cred(siocb->scm, UNIXCB(skb).pid, UNIXCB(skb).cred); + scm_set_cred_noref(siocb->scm, UNIXCB(skb).pid, + UNIXCB(skb).cred); check_creds = 1; }