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:
parent
7ab42b2253
commit
4395e552e2
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user