Change so_cred's type to a ucred, not a pcred. THis makes more sense, actually.

Make a sonewconn3() which takes an extra argument (proc) so new sockets created
with sonewconn() from a user's system call get the correct credentials, not
just the parent's credentials.
This commit is contained in:
green 1999-09-19 02:17:02 +00:00
parent 7ab42b2253
commit 4395e552e2
10 changed files with 55 additions and 46 deletions

View File

@ -44,6 +44,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/resourcevar.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@ -203,6 +204,16 @@ sonewconn(head, connstatus)
register struct socket *head;
int connstatus;
{
return (sonewconn3(head, connstatus, NULL));
}
struct socket *
sonewconn3(head, connstatus, p)
register struct socket *head;
int connstatus;
struct proc *p;
{
register struct socket *so;
if (head->so_qlen > 3 * head->so_qlimit / 2)
@ -217,12 +228,10 @@ sonewconn(head, connstatus)
so->so_state = head->so_state | SS_NOFDREF;
so->so_proto = head->so_proto;
so->so_timeo = head->so_timeo;
so->so_cred = head->so_cred;
if (so->so_cred)
so->so_cred->p_refcnt++;
(void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
so->so_cred = p ? p->p_ucred : head->so_cred;
crhold(so->so_cred);
if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat) ||
(*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
sodealloc(so);
return ((struct socket *)0);
}
@ -921,7 +930,7 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
xso->so_oobmark = so->so_oobmark;
sbtoxsockbuf(&so->so_snd, &xso->so_snd);
sbtoxsockbuf(&so->so_rcv, &xso->so_rcv);
xso->so_uid = so->so_cred ? so->so_cred->pc_ucred->cr_uid : -1;
xso->so_uid = so->so_cred->cr_uid;
}
/*

View File

@ -125,10 +125,8 @@ socreate(dom, aso, type, proto, p)
TAILQ_INIT(&so->so_incomp);
TAILQ_INIT(&so->so_comp);
so->so_type = type;
if (p) {
so->so_cred = p->p_cred;
so->so_cred->p_refcnt++;
} else so->so_cred = NULL;
so->so_cred = p->p_ucred;
crhold(so->so_cred);
so->so_proto = prp;
error = (*prp->pr_usrreqs->pru_attach)(so, proto, p);
if (error) {
@ -158,11 +156,9 @@ void
sodealloc(so)
struct socket *so;
{
so->so_gencnt = ++so_gencnt;
if (so->so_cred && --so->so_cred->p_refcnt == 0) {
crfree(so->so_cred->pc_ucred);
FREE(so->so_cred, M_SUBPROC);
}
crfree(so->so_cred);
zfreei(so->so_zone, so);
}

View File

@ -44,6 +44,7 @@
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/protosw.h>
#include <sys/resourcevar.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/socketvar.h>
@ -203,6 +204,16 @@ sonewconn(head, connstatus)
register struct socket *head;
int connstatus;
{
return (sonewconn3(head, connstatus, NULL));
}
struct socket *
sonewconn3(head, connstatus, p)
register struct socket *head;
int connstatus;
struct proc *p;
{
register struct socket *so;
if (head->so_qlen > 3 * head->so_qlimit / 2)
@ -217,12 +228,10 @@ sonewconn(head, connstatus)
so->so_state = head->so_state | SS_NOFDREF;
so->so_proto = head->so_proto;
so->so_timeo = head->so_timeo;
so->so_cred = head->so_cred;
if (so->so_cred)
so->so_cred->p_refcnt++;
(void) soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat);
if ((*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
so->so_cred = p ? p->p_ucred : head->so_cred;
crhold(so->so_cred);
if (soreserve(so, head->so_snd.sb_hiwat, head->so_rcv.sb_hiwat) ||
(*so->so_proto->pr_usrreqs->pru_attach)(so, 0, NULL)) {
sodealloc(so);
return ((struct socket *)0);
}
@ -921,7 +930,7 @@ sotoxsocket(struct socket *so, struct xsocket *xso)
xso->so_oobmark = so->so_oobmark;
sbtoxsockbuf(&so->so_snd, &xso->so_snd);
sbtoxsockbuf(&so->so_rcv, &xso->so_rcv);
xso->so_uid = so->so_cred ? so->so_cred->pc_ucred->cr_uid : -1;
xso->so_uid = so->so_cred->cr_uid;
}
/*

View File

@ -623,7 +623,7 @@ unp_connect(so, nam, p)
}
if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
if ((so2->so_options & SO_ACCEPTCONN) == 0 ||
(so3 = sonewconn(so2, 0)) == 0) {
(so3 = sonewconn3(so2, 0, p)) == 0) {
error = ECONNREFUSED;
goto bad;
}

View File

@ -202,7 +202,7 @@ in_pcbbind(inp, nam, p)
return (EACCES);
if (p && p->p_prison)
prison = 1;
if (so->so_cred && so->so_cred->p_ruid != 0 &&
if (so->so_cred->cr_uid != 0 &&
!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) {
t = in_pcblookup_local(inp->inp_pcbinfo,
sin->sin_addr, lport,
@ -212,9 +212,8 @@ in_pcbbind(inp, nam, p)
ntohl(t->inp_laddr.s_addr) != INADDR_ANY ||
(t->inp_socket->so_options &
SO_REUSEPORT) == 0) &&
(t->inp_socket->so_cred) &&
(so->so_cred->p_ruid !=
t->inp_socket->so_cred->p_ruid))
(so->so_cred->cr_uid !=
t->inp_socket->so_cred->cr_uid))
return (EADDRINUSE);
}
t = in_pcblookup_local(pcbinfo, sin->sin_addr,

View File

@ -698,13 +698,13 @@ non_ip: ip = NULL ;
P = in_pcblookup_hash(&tcbinfo, ip->ip_src,
tcp->th_sport, ip->ip_dst, tcp->th_dport, 0);
if (P && P->inp_socket && P->inp_socket->so_cred) {
if (P && P->inp_socket) {
if (f->fw_flg & IP_FW_F_UID) {
if (P->inp_socket->so_cred->p_ruid !=
if (P->inp_socket->so_cred->cr_uid !=
f->fw_uid)
continue;
} else if (!groupmember(f->fw_gid,
P->inp_socket->so_cred->pc_ucred))
P->inp_socket->so_cred))
continue;
} else continue;
@ -729,13 +729,13 @@ non_ip: ip = NULL ;
P = in_pcblookup_hash(&udbinfo, ip->ip_src,
udp->uh_sport, ip->ip_dst, udp->uh_dport, 1);
if (P && P->inp_socket && P->inp_socket->so_cred) {
if (P && P->inp_socket) {
if (f->fw_flg & IP_FW_F_UID) {
if (P->inp_socket->so_cred->p_ruid !=
if (P->inp_socket->so_cred->cr_uid !=
f->fw_uid)
continue;
} else if (!groupmember(f->fw_gid,
P->inp_socket->so_cred->pc_ucred))
P->inp_socket->so_cred))
continue;
} else continue;

View File

@ -641,13 +641,11 @@ tcp_getcred SYSCTL_HANDLER_ARGS
s = splnet();
inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
addrs[0].sin_addr, addrs[0].sin_port, 0);
if (inp == NULL || inp->inp_socket == NULL ||
inp->inp_socket->so_cred == NULL) {
if (inp == NULL || inp->inp_socket == NULL) {
error = ENOENT;
goto out;
}
error = SYSCTL_OUT(req, inp->inp_socket->so_cred->pc_ucred,
sizeof(struct ucred));
error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
out:
splx(s);
return (error);

View File

@ -641,13 +641,11 @@ tcp_getcred SYSCTL_HANDLER_ARGS
s = splnet();
inp = in_pcblookup_hash(&tcbinfo, addrs[1].sin_addr, addrs[1].sin_port,
addrs[0].sin_addr, addrs[0].sin_port, 0);
if (inp == NULL || inp->inp_socket == NULL ||
inp->inp_socket->so_cred == NULL) {
if (inp == NULL || inp->inp_socket == NULL) {
error = ENOENT;
goto out;
}
error = SYSCTL_OUT(req, inp->inp_socket->so_cred->pc_ucred,
sizeof(struct ucred));
error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
out:
splx(s);
return (error);

View File

@ -473,13 +473,11 @@ udp_getcred SYSCTL_HANDLER_ARGS
s = splnet();
inp = in_pcblookup_hash(&udbinfo, addrs[1].sin_addr, addrs[1].sin_port,
addrs[0].sin_addr, addrs[0].sin_port, 1);
if (inp == NULL || inp->inp_socket == NULL ||
inp->inp_socket->so_cred == NULL) {
if (inp == NULL || inp->inp_socket == NULL) {
error = ENOENT;
goto out;
}
error = SYSCTL_OUT(req, inp->inp_socket->so_cred->pc_ucred,
sizeof(struct ucred));
error = SYSCTL_OUT(req, inp->inp_socket->so_cred, sizeof(struct ucred));
out:
splx(s);
return (error);

View File

@ -105,7 +105,7 @@ struct socket {
void (*so_upcall) __P((struct socket *, void *, int));
void *so_upcallarg;
struct pcred *so_cred; /* user credentials */
struct ucred *so_cred; /* user credentials */
/* NB: generation count must not be first; easiest to make it last. */
so_gen_t so_gencnt; /* generation count */
void *so_emuldata; /* private data for emulators */
@ -349,6 +349,8 @@ struct socket *
sodropablereq __P((struct socket *head));
struct socket *
sonewconn __P((struct socket *head, int connstatus));
struct socket *
sonewconn3 __P((struct socket *head, int connstatus, struct proc *p));
int sooptcopyin __P((struct sockopt *sopt, void *buf, size_t len,
size_t minlen));
int sooptcopyout __P((struct sockopt *sopt, void *buf, size_t len));