summaryrefslogtreecommitdiff
path: root/net/netfilter/xt_qtaguid.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/netfilter/xt_qtaguid.c')
-rw-r--r--net/netfilter/xt_qtaguid.c160
1 files changed, 75 insertions, 85 deletions
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index 59c719ecf35e..48aa143eabd9 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -1174,6 +1174,38 @@ static void iface_stat_update(struct net_device *net_dev, bool stash_only)
spin_unlock_bh(&iface_stat_list_lock);
}
+/* Guarantied to return a net_device that has a name */
+static void get_dev_and_dir(const struct sk_buff *skb,
+ struct xt_action_param *par,
+ enum ifs_tx_rx *direction,
+ const struct net_device **el_dev)
+{
+ BUG_ON(!direction || !el_dev);
+
+ if (par->in) {
+ *el_dev = par->in;
+ *direction = IFS_RX;
+ } else if (par->out) {
+ *el_dev = par->out;
+ *direction = IFS_TX;
+ } else {
+ pr_err("qtaguid[%d]: %s(): no par->in/out?!!\n",
+ par->hooknum, __func__);
+ BUG();
+ }
+ if (unlikely(!(*el_dev)->name)) {
+ pr_err("qtaguid[%d]: %s(): no dev->name?!!\n",
+ par->hooknum, __func__);
+ BUG();
+ }
+ if (skb->dev && *el_dev != skb->dev) {
+ MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs par->%s=%p %s\n",
+ par->hooknum, skb->dev, skb->dev->name,
+ *direction == IFS_RX ? "in" : "out", *el_dev,
+ (*el_dev)->name);
+ }
+}
+
/*
* Update stats for the specified interface from the skb.
* Do nothing if the entry
@@ -1185,50 +1217,27 @@ static void iface_stat_update_from_skb(const struct sk_buff *skb,
{
struct iface_stat *entry;
const struct net_device *el_dev;
- enum ifs_tx_rx direction = par->in ? IFS_RX : IFS_TX;
+ enum ifs_tx_rx direction;
int bytes = skb->len;
int proto;
- if (!skb->dev) {
- MT_DEBUG("qtaguid[%d]: no skb->dev\n", par->hooknum);
- el_dev = par->in ? : par->out;
- } else {
- const struct net_device *other_dev;
- el_dev = skb->dev;
- other_dev = par->in ? : par->out;
- if (el_dev != other_dev) {
- MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs "
- "par->(in/out)=%p %s\n",
- par->hooknum, el_dev, el_dev->name, other_dev,
- other_dev->name);
- }
- }
-
- if (unlikely(!el_dev)) {
- pr_err_ratelimited("qtaguid[%d]: %s(): no par->in/out?!!\n",
- par->hooknum, __func__);
- BUG();
- } else if (unlikely(!el_dev->name)) {
- pr_err_ratelimited("qtaguid[%d]: %s(): no dev->name?!!\n",
- par->hooknum, __func__);
- BUG();
- } else {
- proto = ipx_proto(skb, par);
- MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n",
- par->hooknum, el_dev->name, el_dev->type,
- par->family, proto);
- }
+ get_dev_and_dir(skb, par, &direction, &el_dev);
+ proto = ipx_proto(skb, par);
+ MT_DEBUG("qtaguid[%d]: iface_stat: %s(%s): "
+ "type=%d fam=%d proto=%d dir=%d\n",
+ par->hooknum, __func__, el_dev->name, el_dev->type,
+ par->family, proto, direction);
spin_lock_bh(&iface_stat_list_lock);
entry = get_iface_entry(el_dev->name);
if (entry == NULL) {
- IF_DEBUG("qtaguid: iface_stat: %s(%s): not tracked\n",
- __func__, el_dev->name);
+ IF_DEBUG("qtaguid[%d]: iface_stat: %s(%s): not tracked\n",
+ par->hooknum, __func__, el_dev->name);
spin_unlock_bh(&iface_stat_list_lock);
return;
}
- IF_DEBUG("qtaguid: %s(%s): entry=%p\n", __func__,
+ IF_DEBUG("qtaguid[%d]: %s(%s): entry=%p\n", par->hooknum, __func__,
el_dev->name, entry);
data_counters_update(&entry->totals_via_skb, 0, direction, proto,
@@ -1293,14 +1302,14 @@ static void if_tag_stat_update(const char *ifname, uid_t uid,
spin_lock_bh(&iface_stat_list_lock);
iface_entry = get_iface_entry(ifname);
if (!iface_entry) {
- pr_err_ratelimited("qtaguid: iface_stat: stat_update() "
+ pr_err_ratelimited("qtaguid: tag_stat: stat_update() "
"%s not found\n", ifname);
spin_unlock_bh(&iface_stat_list_lock);
return;
}
/* It is ok to process data when an iface_entry is inactive */
- MT_DEBUG("qtaguid: iface_stat: stat_update() dev=%s entry=%p\n",
+ MT_DEBUG("qtaguid: tag_stat: stat_update() dev=%s entry=%p\n",
ifname, iface_entry);
/*
@@ -1317,7 +1326,7 @@ static void if_tag_stat_update(const char *ifname, uid_t uid,
tag = combine_atag_with_uid(acct_tag, uid);
uid_tag = make_tag_from_uid(uid);
}
- MT_DEBUG("qtaguid: iface_stat: stat_update(): "
+ MT_DEBUG("qtaguid: tag_stat: stat_update(): "
" looking for tag=0x%llx (uid=%u) in ife=%p\n",
tag, get_uid_from_tag(tag), iface_entry);
/* Loop over tag list under this interface for {acct_tag,uid_tag} */
@@ -1577,8 +1586,8 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb,
struct sock *sk;
unsigned int hook_mask = (1 << par->hooknum);
- MT_DEBUG("qtaguid: find_sk(skb=%p) hooknum=%d family=%d\n", skb,
- par->hooknum, par->family);
+ MT_DEBUG("qtaguid[%d]: find_sk(skb=%p) family=%d\n",
+ par->hooknum, skb, par->family);
/*
* Let's not abuse the the xt_socket_get*_sk(), or else it will
@@ -1599,8 +1608,8 @@ static struct sock *qtaguid_find_sk(const struct sk_buff *skb,
}
if (sk) {
- MT_DEBUG("qtaguid: %p->sk_proto=%u "
- "->sk_state=%d\n", sk, sk->sk_protocol, sk->sk_state);
+ MT_DEBUG("qtaguid[%d]: %p->sk_proto=%u->sk_state=%d\n",
+ par->hooknum, sk, sk->sk_protocol, sk->sk_state);
/*
* When in TCP_TIME_WAIT the sk is not a "struct sock" but
* "struct inet_timewait_sock" which is missing fields.
@@ -1618,37 +1627,19 @@ static void account_for_uid(const struct sk_buff *skb,
struct xt_action_param *par)
{
const struct net_device *el_dev;
+ enum ifs_tx_rx direction;
+ int proto;
- if (!skb->dev) {
- MT_DEBUG("qtaguid[%d]: no skb->dev\n", par->hooknum);
- el_dev = par->in ? : par->out;
- } else {
- const struct net_device *other_dev;
- el_dev = skb->dev;
- other_dev = par->in ? : par->out;
- if (el_dev != other_dev) {
- MT_DEBUG("qtaguid[%d]: skb->dev=%p %s vs "
- "par->(in/out)=%p %s\n",
- par->hooknum, el_dev, el_dev->name, other_dev,
- other_dev->name);
- }
- }
-
- if (unlikely(!el_dev)) {
- pr_info("qtaguid[%d]: no par->in/out?!!\n", par->hooknum);
- } else if (unlikely(!el_dev->name)) {
- pr_info("qtaguid[%d]: no dev->name?!!\n", par->hooknum);
- } else {
- int proto = ipx_proto(skb, par);
- MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d\n",
- par->hooknum, el_dev->name, el_dev->type,
- par->family, proto);
+ get_dev_and_dir(skb, par, &direction, &el_dev);
+ proto = ipx_proto(skb, par);
+ MT_DEBUG("qtaguid[%d]: dev name=%s type=%d fam=%d proto=%d dir=%d\n",
+ par->hooknum, el_dev->name, el_dev->type,
+ par->family, proto, direction);
- if_tag_stat_update(el_dev->name, uid,
- skb->sk ? skb->sk : alternate_sk,
- par->in ? IFS_RX : IFS_TX,
- proto, skb->len);
- }
+ if_tag_stat_update(el_dev->name, uid,
+ skb->sk ? skb->sk : alternate_sk,
+ direction,
+ proto, skb->len);
}
static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
@@ -1660,6 +1651,11 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
uid_t sock_uid;
bool res;
bool set_sk_callback_lock = false;
+ /*
+ * TODO: unhack how to force just accounting.
+ * For now we only do tag stats when the uid-owner is not requested
+ */
+ bool do_tag_stat = !(info->match & XT_QTAGUID_UID);
if (unlikely(module_passive))
return (info->match ^ info->invert) == 0;
@@ -1724,12 +1720,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
* couldn't find the owner, so for now we just count them
* against the system.
*/
- /*
- * TODO: unhack how to force just accounting.
- * For now we only do iface stats when the uid-owner is not
- * requested.
- */
- if (!(info->match & XT_QTAGUID_UID))
+ if (do_tag_stat)
account_for_uid(skb, sk, 0, par);
MT_DEBUG("qtaguid[%d]: leaving (sk=NULL)\n", par->hooknum);
res = (info->match ^ info->invert) == 0;
@@ -1740,12 +1731,9 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
goto put_sock_ret_res;
}
sock_uid = sk->sk_uid;
- /*
- * TODO: unhack how to force just accounting.
- * For now we only do iface stats when the uid-owner is not requested
- */
- if (!(info->match & XT_QTAGUID_UID))
- account_for_uid(skb, sk, from_kuid(&init_user_ns, sock_uid), par);
+ if (do_tag_stat)
+ account_for_uid(skb, sk, from_kuid(&init_user_ns, sock_uid),
+ par);
/*
* The following two tests fail the match when:
@@ -1772,16 +1760,18 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par)
set_sk_callback_lock = true;
read_lock_bh(&sk->sk_callback_lock);
MT_DEBUG("qtaguid[%d]: sk=%p->sk_socket=%p->file=%p\n",
- par->hooknum, sk, sk->sk_socket,
- sk->sk_socket ? sk->sk_socket->file : (void *)-1LL);
+ par->hooknum, sk, sk->sk_socket,
+ sk->sk_socket ? sk->sk_socket->file : (void *)-1LL);
filp = sk->sk_socket ? sk->sk_socket->file : NULL;
if (!filp) {
- res = ((info->match ^ info->invert) & XT_QTAGUID_GID) == 0;
+ res = ((info->match ^ info->invert) &
+ XT_QTAGUID_GID) == 0;
atomic64_inc(&qtu_events.match_no_sk_gid);
goto put_sock_ret_res;
}
MT_DEBUG("qtaguid[%d]: filp...uid=%u\n",
- par->hooknum, filp ? from_kuid(&init_user_ns, filp->f_cred->fsuid) : -1);
+ par->hooknum, filp ?
+ from_kuid(&init_user_ns, filp->f_cred->fsuid) : -1);
if ((gid_gte(filp->f_cred->fsgid, gid_min) &&
gid_lte(filp->f_cred->fsgid, gid_max)) ^
!(info->invert & XT_QTAGUID_GID)) {