net80211: factor out the priv(9) checks into OS specifc code.

Factor out the priv(9) checks into OS specifc code so other OSes can equally
implement them.  This sorts out those XXX in the net80211 code.
We provide 3 arguments (cmd, vap, ifp) where available to the functions, in
order to allow other OSes to use that data but also in case we'd add auditing
to these check to have the information available. For now the arguments are
marked __unused.

PR:		249403
Reported by:	martin(NetBSD)
Reviewed by:	adrian, martin(NetBSD)
MFC after:	10 days
Sponsored by:	Rubicon Communications, LLC (d/b/a "Netgate")
Differential Revision:	https://reviews.freebsd.org/D26541
This commit is contained in:
Bjoern A. Zeeb 2020-10-18 21:34:04 +00:00
parent 3ac62888fc
commit 01e579408b
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=366817
3 changed files with 57 additions and 12 deletions

View File

@ -75,6 +75,42 @@ SYSCTL_INT(_net_wlan, OID_AUTO, debug, CTLFLAG_RW, &ieee80211_debug,
static const char wlanname[] = "wlan";
static struct if_clone *wlan_cloner;
/*
* priv(9) NET80211 checks.
* Return 0 if operation is allowed, E* (usually EPERM) otherwise.
*/
int
ieee80211_priv_check_vap_getkey(u_long cmd __unused,
struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
{
return (priv_check(curthread, PRIV_NET80211_VAP_GETKEY));
}
int
ieee80211_priv_check_vap_manage(u_long cmd __unused,
struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
{
return (priv_check(curthread, PRIV_NET80211_VAP_MANAGE));
}
int
ieee80211_priv_check_vap_setmac(u_long cmd __unused,
struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
{
return (priv_check(curthread, PRIV_NET80211_VAP_SETMAC));
}
int
ieee80211_priv_check_create_vap(u_long cmd __unused,
struct ieee80211vap *vap __unused, struct ifnet *ifp __unused)
{
return (priv_check(curthread, PRIV_NET80211_CREATE_VAP));
}
static int
wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
{
@ -83,7 +119,7 @@ wlan_clone_create(struct if_clone *ifc, int unit, caddr_t params)
struct ieee80211com *ic;
int error;
error = priv_check(curthread, PRIV_NET80211_CREATE_VAP);
error = ieee80211_priv_check_create_vap(0, NULL, NULL);
if (error)
return error;

View File

@ -42,6 +42,19 @@
#include <net/debugnet.h>
/*
* priv(9) NET80211 checks.
*/
struct ieee80211vap;
int ieee80211_priv_check_vap_getkey(u_long, struct ieee80211vap *,
struct ifnet *);
int ieee80211_priv_check_vap_manage(u_long, struct ieee80211vap *,
struct ifnet *);
int ieee80211_priv_check_vap_setmac(u_long, struct ieee80211vap *,
struct ifnet *);
int ieee80211_priv_check_create_vap(u_long, struct ieee80211vap *,
struct ifnet *);
/*
* Common state locking definitions.
*/

View File

@ -40,7 +40,6 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/priv.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/systm.h>
@ -72,7 +71,8 @@ static int ieee80211_scanreq(struct ieee80211vap *,
struct ieee80211_scan_req *);
static int
ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
ieee80211_ioctl_getkey(u_long cmd, struct ieee80211vap *vap,
struct ieee80211req *ireq)
{
struct ieee80211com *ic = vap->iv_ic;
struct ieee80211_node *ni;
@ -106,8 +106,7 @@ ieee80211_ioctl_getkey(struct ieee80211vap *vap, struct ieee80211req *ireq)
ik.ik_flags = wk->wk_flags & (IEEE80211_KEY_XMIT | IEEE80211_KEY_RECV);
if (wk->wk_keyix == vap->iv_def_txkey)
ik.ik_flags |= IEEE80211_KEY_DEFAULT;
/* XXX TODO: move priv check to ieee80211_freebsd.c */
if (priv_check(curthread, PRIV_NET80211_VAP_GETKEY) == 0) {
if (ieee80211_priv_check_vap_getkey(cmd, vap, NULL) == 0) {
/* NB: only root can read key data */
ik.ik_keyrsc = wk->wk_keyrsc[IEEE80211_NONQOS_TID];
ik.ik_keytsc = wk->wk_keytsc;
@ -822,8 +821,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
return EINVAL;
len = (u_int) vap->iv_nw_keys[kid].wk_keylen;
/* NB: only root can read WEP keys */
/* XXX TODO: move priv check to ieee80211_freebsd.c */
if (priv_check(curthread, PRIV_NET80211_VAP_GETKEY) == 0) {
if (ieee80211_priv_check_vap_getkey(cmd, vap, NULL) == 0) {
bcopy(vap->iv_nw_keys[kid].wk_key, tmpkey, len);
} else {
bzero(tmpkey, len);
@ -916,7 +914,7 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
ireq->i_val = (vap->iv_flags & IEEE80211_F_NOBRIDGE) == 0;
break;
case IEEE80211_IOC_WPAKEY:
error = ieee80211_ioctl_getkey(vap, ireq);
error = ieee80211_ioctl_getkey(cmd, vap, ireq);
break;
case IEEE80211_IOC_CHANINFO:
error = ieee80211_ioctl_getchaninfo(vap, ireq);
@ -3630,8 +3628,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
(struct ieee80211req *) data);
break;
case SIOCS80211:
/* XXX TODO: move priv check to ieee80211_freebsd.c */
error = priv_check(curthread, PRIV_NET80211_VAP_MANAGE);
error = ieee80211_priv_check_vap_manage(cmd, vap, ifp);
if (error == 0)
error = ieee80211_ioctl_set80211(vap, cmd,
(struct ieee80211req *) data);
@ -3677,8 +3674,7 @@ ieee80211_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
}
break;
case SIOCSIFLLADDR:
/* XXX TODO: move priv check to ieee80211_freebsd.c */
error = priv_check(curthread, PRIV_NET80211_VAP_SETMAC);
error = ieee80211_priv_check_vap_setmac(cmd, vap, ifp);
if (error == 0)
break;
/* Fallthrough */