Rather than passing around a cached 'priv', pass in an ucred to
ipsec*_set_policy and do the privilege check only if needed. Try to assimilate both ip*_ctloutput code blocks calling ipsec*_set_policy. Reviewed by: rwatson
This commit is contained in:
parent
a4afe9200c
commit
c26fe973a3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=175892
@ -43,10 +43,12 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/ucred.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/netisr.h>
|
||||
@ -972,33 +974,16 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
|
||||
case IP_IPSEC_POLICY:
|
||||
{
|
||||
caddr_t req;
|
||||
size_t len = 0;
|
||||
int priv;
|
||||
struct mbuf *m;
|
||||
int optname;
|
||||
|
||||
if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
|
||||
break;
|
||||
if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
|
||||
break;
|
||||
if (sopt->sopt_td != NULL) {
|
||||
/*
|
||||
* XXXRW: Would be more desirable to do this
|
||||
* one layer down so that we only exercise
|
||||
* privilege if it is needed.
|
||||
*/
|
||||
error = priv_check(sopt->sopt_td,
|
||||
PRIV_NETINET_IPSEC);
|
||||
if (error)
|
||||
priv = 0;
|
||||
else
|
||||
priv = 1;
|
||||
} else
|
||||
priv = 1;
|
||||
req = mtod(m, caddr_t);
|
||||
len = m->m_len;
|
||||
optname = sopt->sopt_name;
|
||||
error = ipsec4_set_policy(inp, optname, req, len, priv);
|
||||
error = ipsec4_set_policy(inp, sopt->sopt_name, req,
|
||||
m->m_len, (sopt->sopt_td != NULL) ?
|
||||
sopt->sopt_td->td_ucred : NULL);
|
||||
m_freem(m);
|
||||
break;
|
||||
}
|
||||
|
@ -68,15 +68,16 @@ __FBSDID("$FreeBSD$");
|
||||
#include "opt_ipsec.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/mbuf.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/priv.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/protosw.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/ucred.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <net/netisr.h>
|
||||
@ -1767,39 +1768,21 @@ do { \
|
||||
|
||||
#ifdef IPSEC
|
||||
case IPV6_IPSEC_POLICY:
|
||||
{
|
||||
caddr_t req = NULL;
|
||||
size_t len = 0;
|
||||
{
|
||||
caddr_t req;
|
||||
struct mbuf *m;
|
||||
int priv = 0;
|
||||
|
||||
if ((error = soopt_getm(sopt, &m)) != 0) /* XXX */
|
||||
break;
|
||||
if ((error = soopt_mcopyin(sopt, m)) != 0) /* XXX */
|
||||
break;
|
||||
if (m) {
|
||||
req = mtod(m, caddr_t);
|
||||
len = m->m_len;
|
||||
}
|
||||
if (sopt->sopt_td != NULL) {
|
||||
/*
|
||||
* XXXRW/XXX-BZ: Would be more desirable to do
|
||||
* this one layer down so that we only exercise
|
||||
* privilege if it is needed.
|
||||
*/
|
||||
error = priv_check(sopt->sopt_td,
|
||||
PRIV_NETINET_IPSEC);
|
||||
if (error)
|
||||
priv = 0;
|
||||
else
|
||||
priv = 1;
|
||||
} else
|
||||
priv = 1;
|
||||
req = mtod(m, caddr_t);
|
||||
error = ipsec6_set_policy(in6p, optname, req,
|
||||
len, priv);
|
||||
m->m_len, (sopt->sopt_td != NULL) ?
|
||||
sopt->sopt_td->td_ucred : NULL);
|
||||
m_freem(m);
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* IPSEC */
|
||||
|
||||
default:
|
||||
|
@ -219,7 +219,7 @@ static int ipsec6_setspidx_ipaddr __P((struct mbuf *, struct secpolicyindex *));
|
||||
static void ipsec_delpcbpolicy __P((struct inpcbpolicy *));
|
||||
static struct secpolicy *ipsec_deepcopy_policy __P((struct secpolicy *src));
|
||||
static int ipsec_set_policy __P((struct secpolicy **pcb_sp,
|
||||
int optname, caddr_t request, size_t len, int priv));
|
||||
int optname, caddr_t request, size_t len, struct ucred *cred));
|
||||
static int ipsec_get_policy __P((struct secpolicy *pcb_sp, struct mbuf **mp));
|
||||
static void vshiftl __P((unsigned char *, int, int));
|
||||
static size_t ipsec_hdrsiz __P((struct secpolicy *));
|
||||
@ -1005,12 +1005,12 @@ ipsec_deepcopy_policy(src)
|
||||
|
||||
/* set policy and ipsec request if present. */
|
||||
static int
|
||||
ipsec_set_policy(pcb_sp, optname, request, len, priv)
|
||||
ipsec_set_policy(pcb_sp, optname, request, len, cred)
|
||||
struct secpolicy **pcb_sp;
|
||||
int optname;
|
||||
caddr_t request;
|
||||
size_t len;
|
||||
int priv;
|
||||
struct ucred *cred;
|
||||
{
|
||||
struct sadb_x_policy *xpl;
|
||||
struct secpolicy *newsp = NULL;
|
||||
@ -1034,8 +1034,11 @@ ipsec_set_policy(pcb_sp, optname, request, len, priv)
|
||||
return EINVAL;
|
||||
|
||||
/* check privileged socket */
|
||||
if (priv == 0 && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS)
|
||||
return EACCES;
|
||||
if (cred != NULL && xpl->sadb_x_policy_type == IPSEC_POLICY_BYPASS) {
|
||||
error = priv_check_cred(cred, PRIV_NETINET_IPSEC, 0);
|
||||
if (error)
|
||||
return EACCES;
|
||||
}
|
||||
|
||||
/* allocation new SP entry */
|
||||
if ((newsp = key_msg2sp(xpl, len, &error)) == NULL)
|
||||
@ -1077,12 +1080,12 @@ ipsec_get_policy(pcb_sp, mp)
|
||||
}
|
||||
|
||||
int
|
||||
ipsec4_set_policy(inp, optname, request, len, priv)
|
||||
ipsec4_set_policy(inp, optname, request, len, cred)
|
||||
struct inpcb *inp;
|
||||
int optname;
|
||||
caddr_t request;
|
||||
size_t len;
|
||||
int priv;
|
||||
struct ucred *cred;
|
||||
{
|
||||
struct sadb_x_policy *xpl;
|
||||
struct secpolicy **pcb_sp;
|
||||
@ -1108,7 +1111,7 @@ ipsec4_set_policy(inp, optname, request, len, priv)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return ipsec_set_policy(pcb_sp, optname, request, len, priv);
|
||||
return ipsec_set_policy(pcb_sp, optname, request, len, cred);
|
||||
}
|
||||
|
||||
int
|
||||
@ -1170,12 +1173,12 @@ ipsec4_delete_pcbpolicy(inp)
|
||||
|
||||
#ifdef INET6
|
||||
int
|
||||
ipsec6_set_policy(in6p, optname, request, len, priv)
|
||||
ipsec6_set_policy(in6p, optname, request, len, cred)
|
||||
struct in6pcb *in6p;
|
||||
int optname;
|
||||
caddr_t request;
|
||||
size_t len;
|
||||
int priv;
|
||||
struct ucred *cred;
|
||||
{
|
||||
struct sadb_x_policy *xpl;
|
||||
struct secpolicy **pcb_sp;
|
||||
@ -1201,7 +1204,7 @@ ipsec6_set_policy(in6p, optname, request, len, priv)
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return ipsec_set_policy(pcb_sp, optname, request, len, priv);
|
||||
return ipsec_set_policy(pcb_sp, optname, request, len, cred);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -370,7 +370,7 @@ extern u_int ipsec_get_reqlevel __P((struct ipsecrequest *));
|
||||
extern int ipsec_in_reject __P((struct secpolicy *, struct mbuf *));
|
||||
|
||||
extern int ipsec4_set_policy __P((struct inpcb *inp, int optname,
|
||||
caddr_t request, size_t len, int priv));
|
||||
caddr_t request, size_t len, struct ucred *cred));
|
||||
extern int ipsec4_get_policy __P((struct inpcb *inpcb, caddr_t request,
|
||||
size_t len, struct mbuf **mp));
|
||||
extern int ipsec4_delete_pcbpolicy __P((struct inpcb *));
|
||||
|
@ -53,7 +53,7 @@ struct inpcb;
|
||||
|
||||
extern int ipsec6_delete_pcbpolicy __P((struct inpcb *));
|
||||
extern int ipsec6_set_policy __P((struct inpcb *inp, int optname,
|
||||
caddr_t request, size_t len, int priv));
|
||||
caddr_t request, size_t len, struct ucred *cred));
|
||||
extern int ipsec6_get_policy
|
||||
__P((struct inpcb *inp, caddr_t request, size_t len, struct mbuf **mp));
|
||||
extern int ipsec6_in_reject __P((struct mbuf *, struct inpcb *));
|
||||
|
Loading…
Reference in New Issue
Block a user