From 84ae7364326ea759f39d9ed6973de30f21d6090d Mon Sep 17 00:00:00 2001
From: Chenbo Feng <fengc@google.com>
Date: Tue, 25 Apr 2017 18:22:55 +0000
Subject: [PATCH] Revert "ANDROID: Add untag hacks to inet_release function"
This reverts commit 9c209b1dcbcd6eaba6d73e3c713cfcb53c334a33.
Change-Id: I8a45da9d42e6c0ecad2f1254eed598b0483707f5
(cherry picked from commit 5b345e8eca9e3a0fefe58a8bd818b6f49715fcba)
---
include/linux/netfilter/xt_qtaguid.h | 1 -
net/ipv4/af_inet.c | 4 --
net/netfilter/xt_qtaguid.c | 87 +++++++++++++++-------------
net/netfilter/xt_qtaguid_internal.h | 2 +
net/netfilter/xt_qtaguid_print.c | 8 +--
5 files changed, 52 insertions(+), 50 deletions(-)
diff --git a/include/linux/netfilter/xt_qtaguid.h b/include/linux/netfilter/xt_qtaguid.h
index adb2e4c39392..ca60fbdec2f3 100644
--- a/include/linux/netfilter/xt_qtaguid.h
+++ b/include/linux/netfilter/xt_qtaguid.h
@@ -10,5 +10,4 @@
#define XT_QTAGUID_SOCKET XT_OWNER_SOCKET
#define xt_qtaguid_match_info xt_owner_match_info
-int qtaguid_untag(struct socket *sock);
#endif /* _XT_QTAGUID_MATCH_H */
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index c312db43d6cf..db333aa0abf8 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -89,7 +89,6 @@
#include <linux/netfilter_ipv4.h>
#include <linux/random.h>
#include <linux/slab.h>
-#include <linux/netfilter/xt_qtaguid.h>
#include <asm/uaccess.h>
@@ -418,9 +417,6 @@ int inet_release(struct socket *sock)
if (sk) {
long timeout;
-#ifdef CONFIG_NETFILTER_XT_MATCH_QTAGUID
- qtaguid_untag(sock);
-#endif
sock_rps_reset_flow(sk);
/* Applications forget to leave groups before exiting */
diff --git a/net/netfilter/xt_qtaguid.c b/net/netfilter/xt_qtaguid.c
index c260adc0fd86..dee6af5d7595 100644
--- a/net/netfilter/xt_qtaguid.c
+++ b/net/netfilter/xt_qtaguid.c
@@ -320,7 +320,7 @@ static void sock_tag_tree_erase(struct rb_root *st_to_free_tree)
st_entry->tag,
get_uid_from_tag(st_entry->tag));
rb_erase(&st_entry->sock_node, st_to_free_tree);
- sock_put(st_entry->sk);
+ sockfd_put(st_entry->socket);
kfree(st_entry);
}
}
@@ -1917,12 +1917,12 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v)
{
struct sock_tag *sock_tag_entry = v;
uid_t uid;
+ long f_count;
CT_DEBUG("qtaguid: proc ctrl pid=%u tgid=%u uid=%u\n",
current->pid, current->tgid, from_kuid(&init_user_ns, current_fsuid()));
if (sock_tag_entry != SEQ_START_TOKEN) {
- int sk_ref_count;
uid = get_uid_from_tag(sock_tag_entry->tag);
CT_DEBUG("qtaguid: proc_read(): sk=%p tag=0x%llx (uid=%u) "
"pid=%u\n",
@@ -1931,13 +1931,13 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v)
uid,
sock_tag_entry->pid
);
- sk_ref_count = atomic_read(
- &sock_tag_entry->sk->sk_refcnt);
+ f_count = atomic_long_read(
+ &sock_tag_entry->socket->file->f_count);
seq_printf(m, "sock=%pK tag=0x%llx (uid=%u) pid=%u "
- "f_count=%d\n",
+ "f_count=%lu\n",
sock_tag_entry->sk,
sock_tag_entry->tag, uid,
- sock_tag_entry->pid, sk_ref_count);
+ sock_tag_entry->pid, f_count);
} else {
seq_printf(m, "events: sockets_tagged=%llu "
"sockets_untagged=%llu "
@@ -2233,8 +2233,8 @@ static int ctrl_cmd_tag(const char *input)
from_kuid(&init_user_ns, current_fsuid()));
goto err;
}
- CT_DEBUG("qtaguid: ctrl_tag(%s): socket->...->sk_refcnt=%d ->sk=%p\n",
- input, atomic_read(&el_socket->sk->sk_refcnt),
+ CT_DEBUG("qtaguid: ctrl_tag(%s): socket->...->f_count=%ld ->sk=%p\n",
+ input, atomic_long_read(&el_socket->file->f_count),
el_socket->sk);
if (argc < 3) {
acct_tag = make_atag_from_value(0);
@@ -2278,9 +2278,16 @@ static int ctrl_cmd_tag(const char *input)
struct tag_ref *prev_tag_ref_entry;
CT_DEBUG("qtaguid: ctrl_tag(%s): retag for sk=%p "
- "st@%p ...->sk_refcnt=%d\n",
+ "st@%p ...->f_count=%ld\n",
input, el_socket->sk, sock_tag_entry,
- atomic_read(&el_socket->sk->sk_refcnt));
+ atomic_long_read(&el_socket->file->f_count));
+ /*
+ * This is a re-tagging, so release the sock_fd that was
+ * locked at the time of the 1st tagging.
+ * There is still the ref from this call's sockfd_lookup() so
+ * it can be done within the spinlock.
+ */
+ sockfd_put(sock_tag_entry->socket);
prev_tag_ref_entry = lookup_tag_ref(sock_tag_entry->tag,
&uid_tag_data_entry);
BUG_ON(IS_ERR_OR_NULL(prev_tag_ref_entry));
@@ -2300,12 +2307,8 @@ static int ctrl_cmd_tag(const char *input)
res = -ENOMEM;
goto err_tag_unref_put;
}
- /*
- * Hold the sk refcount here to make sure the sk pointer cannot
- * be freed and reused
- */
- sock_hold(el_socket->sk);
sock_tag_entry->sk = el_socket->sk;
+ sock_tag_entry->socket = el_socket;
sock_tag_entry->pid = current->tgid;
sock_tag_entry->tag = combine_atag_with_uid(acct_tag, uid_int);
spin_lock_bh(&uid_tag_data_tree_lock);
@@ -2332,11 +2335,10 @@ static int ctrl_cmd_tag(const char *input)
atomic64_inc(&qtu_events.sockets_tagged);
}
spin_unlock_bh(&sock_tag_list_lock);
- /* We keep the ref to the sk until it is untagged */
- CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%p ...->sk_refcnt=%d\n",
+ /* We keep the ref to the socket (file) until it is untagged */
+ CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%p ...->f_count=%ld\n",
input, sock_tag_entry,
- atomic_read(&el_socket->sk->sk_refcnt));
- sockfd_put(el_socket);
+ atomic_long_read(&el_socket->file->f_count));
return 0;
err_tag_unref_put:
@@ -2344,8 +2346,8 @@ err_tag_unref_put:
tag_ref_entry->num_sock_tags--;
free_tag_ref_from_utd_entry(tag_ref_entry, uid_tag_data_entry);
err_put:
- CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->sk_refcnt=%d\n",
- input, atomic_read(&el_socket->sk->sk_refcnt) - 1);
+ CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->f_count=%ld\n",
+ input, atomic_long_read(&el_socket->file->f_count) - 1);
/* Release the sock_fd that was grabbed by sockfd_lookup(). */
sockfd_put(el_socket);
return res;
@@ -2361,6 +2363,10 @@ static int ctrl_cmd_untag(const char *input)
int sock_fd = 0;
struct socket *el_socket;
int res, argc;
+ struct sock_tag *sock_tag_entry;
+ struct tag_ref *tag_ref_entry;
+ struct uid_tag_data *utd_entry;
+ struct proc_qtu_data *pqd_entry;
argc = sscanf(input, "%c %d", &cmd, &sock_fd);
CT_DEBUG("qtaguid: ctrl_untag(%s): argc=%d cmd=%c sock_fd=%d\n",
@@ -2380,26 +2386,12 @@ static int ctrl_cmd_untag(const char *input)
CT_DEBUG("qtaguid: ctrl_untag(%s): socket->...->f_count=%ld ->sk=%p\n",
input, atomic_long_read(&el_socket->file->f_count),
el_socket->sk);
- res = qtaguid_untag(el_socket);
- sockfd_put(el_socket);
-err:
- return res;
-}
-
-int qtaguid_untag(struct socket *el_socket)
-{
- int res;
- struct sock_tag *sock_tag_entry;
- struct tag_ref *tag_ref_entry;
- struct uid_tag_data *utd_entry;
- struct proc_qtu_data *pqd_entry;
-
spin_lock_bh(&sock_tag_list_lock);
sock_tag_entry = get_sock_stat_nl(el_socket->sk);
if (!sock_tag_entry) {
spin_unlock_bh(&sock_tag_list_lock);
res = -EINVAL;
- return res;
+ goto err_put;
}
/*
* The socket already belongs to the current process
@@ -2433,17 +2425,30 @@ int qtaguid_untag(struct socket *el_socket)
tag_ref_entry->num_sock_tags--;
spin_unlock_bh(&sock_tag_list_lock);
/*
- * Release the sock_fd that was grabbed at tag time.
+ * Release the sock_fd that was grabbed at tag time,
+ * and once more for the sockfd_lookup() here.
*/
- sock_put(sock_tag_entry->sk);
- CT_DEBUG("qtaguid: done. st@%p ...->sk_refcnt=%d\n",
- sock_tag_entry,
- atomic_read(&el_socket->sk->sk_refcnt));
+ sockfd_put(sock_tag_entry->socket);
+ CT_DEBUG("qtaguid: ctrl_untag(%s): done. st@%p ...->f_count=%ld\n",
+ input, sock_tag_entry,
+ atomic_long_read(&el_socket->file->f_count) - 1);
+ sockfd_put(el_socket);
kfree(sock_tag_entry);
atomic64_inc(&qtu_events.sockets_untagged);
return 0;
+
+err_put:
+ CT_DEBUG("qtaguid: ctrl_untag(%s): done. socket->...->f_count=%ld\n",
+ input, atomic_long_read(&el_socket->file->f_count) - 1);
+ /* Release the sock_fd that was grabbed by sockfd_lookup(). */
+ sockfd_put(el_socket);
+ return res;
+
+err:
+ CT_DEBUG("qtaguid: ctrl_untag(%s): done.\n", input);
+ return res;
}
static ssize_t qtaguid_ctrl_parse(const char *input, size_t count)
diff --git a/net/netfilter/xt_qtaguid_internal.h b/net/netfilter/xt_qtaguid_internal.h
index 8178fbdfb036..6dc14a9c6889 100644
--- a/net/netfilter/xt_qtaguid_internal.h
+++ b/net/netfilter/xt_qtaguid_internal.h
@@ -256,6 +256,8 @@ struct iface_stat_work {
struct sock_tag {
struct rb_node sock_node;
struct sock *sk; /* Only used as a number, never dereferenced */
+ /* The socket is needed for sockfd_put() */
+ struct socket *socket;
/* Used to associate with a given pid */
struct list_head list; /* in proc_qtu_data.sock_tag_list */
pid_t pid;
diff --git a/net/netfilter/xt_qtaguid_print.c b/net/netfilter/xt_qtaguid_print.c
index 2a7190d285e6..f6a00a3520ed 100644
--- a/net/netfilter/xt_qtaguid_print.c
+++ b/net/netfilter/xt_qtaguid_print.c
@@ -24,7 +24,7 @@
#include <linux/rbtree.h>
#include <linux/slab.h>
#include <linux/spinlock_types.h>
-#include <net/sock.h>
+
#include "xt_qtaguid_internal.h"
#include "xt_qtaguid_print.h"
@@ -237,10 +237,10 @@ char *pp_sock_tag(struct sock_tag *st)
tag_str = pp_tag_t(&st->tag);
res = kasprintf(GFP_ATOMIC, "sock_tag@%p{"
"sock_node=rb_node{...}, "
- "sk=%p (f_count=%d), list=list_head{...}, "
+ "sk=%p socket=%p (f_count=%lu), list=list_head{...}, "
"pid=%u, tag=%s}",
- st, st->sk, atomic_read(
- &st->sk->sk_refcnt),
+ st, st->sk, st->socket, atomic_long_read(
+ &st->socket->file->f_count),
st->pid, tag_str);
_bug_on_err_or_null(res);
kfree(tag_str);
--
GitLab