Loading net/netfilter/xt_qtaguid.c +69 −81 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 { 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\n", par->hooknum, el_dev->name, el_dev->type, par->family, proto); } 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, Loading Loading @@ -1293,13 +1302,13 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, 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); 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); /* Loading @@ -1316,7 +1325,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} */ Loading Loading @@ -1576,8 +1585,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 Loading @@ -1598,8 +1607,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. Loading @@ -1618,38 +1627,20 @@ 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", 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); par->family, proto, direction); if_tag_stat_update(el_dev->name, uid, skb->sk ? skb->sk : alternate_sk, par->in ? IFS_RX : IFS_TX, direction, proto, skb->len); } } static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) { Loading @@ -1660,6 +1651,11 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) kuid_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; Loading Loading @@ -1733,12 +1729,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?sk->sk_socket)=%p\n", par->hooknum, Loading @@ -1753,6 +1744,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) filp = sk->sk_socket->file; if (filp == NULL) { MT_DEBUG("qtaguid[%d]: leaving filp=NULL\n", par->hooknum); if (do_tag_stat) account_for_uid(skb, sk, 0, par); res = ((info->match ^ info->invert) & (XT_QTAGUID_UID | XT_QTAGUID_GID)) == 0; Loading @@ -1760,11 +1752,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) goto put_sock_ret_res; } sock_uid = filp->f_cred->fsuid; /* * 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, from_kuid(&init_user_ns, sock_uid), par); /* Loading Loading
net/netfilter/xt_qtaguid.c +69 −81 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 { 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\n", par->hooknum, el_dev->name, el_dev->type, par->family, proto); } 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, Loading Loading @@ -1293,13 +1302,13 @@ static void if_tag_stat_update(const char *ifname, uid_t uid, 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); 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); /* Loading @@ -1316,7 +1325,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} */ Loading Loading @@ -1576,8 +1585,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 Loading @@ -1598,8 +1607,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. Loading @@ -1618,38 +1627,20 @@ 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", 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); par->family, proto, direction); if_tag_stat_update(el_dev->name, uid, skb->sk ? skb->sk : alternate_sk, par->in ? IFS_RX : IFS_TX, direction, proto, skb->len); } } static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) { Loading @@ -1660,6 +1651,11 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) kuid_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; Loading Loading @@ -1733,12 +1729,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?sk->sk_socket)=%p\n", par->hooknum, Loading @@ -1753,6 +1744,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) filp = sk->sk_socket->file; if (filp == NULL) { MT_DEBUG("qtaguid[%d]: leaving filp=NULL\n", par->hooknum); if (do_tag_stat) account_for_uid(skb, sk, 0, par); res = ((info->match ^ info->invert) & (XT_QTAGUID_UID | XT_QTAGUID_GID)) == 0; Loading @@ -1760,11 +1752,7 @@ static bool qtaguid_mt(const struct sk_buff *skb, struct xt_action_param *par) goto put_sock_ret_res; } sock_uid = filp->f_cred->fsuid; /* * 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, from_kuid(&init_user_ns, sock_uid), par); /* Loading