netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 0/2] Incorrect memory access when using TAP
@ 2019-09-29 11:05 Amadeusz Sławiński
  2019-09-29 11:05 ` [RFC PATCH 1/2] net: tap: Fix incorrect memory access Amadeusz Sławiński
  2019-09-29 11:05 ` [RFC PATCH 2/2] net: tun: " Amadeusz Sławiński
  0 siblings, 2 replies; 3+ messages in thread
From: Amadeusz Sławiński @ 2019-09-29 11:05 UTC (permalink / raw)
  To: David S . Miller, netdev; +Cc: Amadeusz Sławiński

Hi,

I've recently started using virt-manager to setup my virtual machines,
along with macvtap bridge. When I start VM I noticed that following
appears in dmesg:

[  125.256517] ==================================================================
[  125.256524] BUG: KASAN: slab-out-of-bounds in sock_init_data+0x262/0x560
[  125.256525] Read of size 4 at addr ffff8887d1825a28 by task libvirtd/3749

[  125.256529] CPU: 1 PID: 3749 Comm: libvirtd Tainted: G                T 5.3.0+ #50
[  125.256530] Hardware name: ASUS All Series/SABERTOOTH Z97 MARK 2, BIOS 3503 04/18/2018
[  125.256531] Call Trace:
[  125.256535]  dump_stack+0x5b/0x88
[  125.256539]  print_address_description.constprop.0+0x19/0x210
[  125.256541]  ? sock_init_data+0x262/0x560
[  125.256543]  __kasan_report.cold+0x1a/0x40
[  125.256545]  ? sock_init_data+0x262/0x560
[  125.256547]  ? sock_init_data+0x262/0x560
[  125.256549]  kasan_report+0x2a/0x40
[  125.256551]  sock_init_data+0x262/0x560
[  125.256554]  tap_open+0x2af/0x580
[  125.256556]  chrdev_open+0x171/0x380
[  125.256558]  ? cdev_put.part.0+0x30/0x30
[  125.256561]  do_dentry_open+0x2dd/0x7f0
[  125.256562]  ? cdev_put.part.0+0x30/0x30
[  125.256564]  ? __ia32_sys_fchdir+0xe0/0xe0
[  125.256567]  ? security_inode_permission+0x56/0x70
[  125.256570]  path_openat+0x94f/0x22e0
[  125.256573]  ? preempt_count_sub+0xf/0xb0
[  125.256576]  ? __rcu_read_unlock+0x79/0x2b0
[  125.256578]  ? path_lookupat.isra.0+0x4c0/0x4c0
[  125.256581]  ? __is_insn_slot_addr+0x56/0x80
[  125.256583]  ? kernel_text_address+0xdc/0xf0
[  125.256585]  ? unwind_get_return_address+0x2d/0x40
[  125.256587]  ? profile_setup.cold+0x96/0x96
[  125.256589]  ? arch_stack_walk+0x8a/0xd0
[  125.256591]  do_filp_open+0x110/0x1a0
[  125.256593]  ? may_open_dev+0x50/0x50
[  125.256595]  ? expand_files+0x9b/0x330
[  125.256596]  ? rb_insert_color+0x32/0x3e0
[  125.256598]  ? copy_fd_bitmaps+0x110/0x110
[  125.256600]  ? preempt_count_sub+0xf/0xb0
[  125.256602]  ? _raw_spin_lock+0x82/0xd0
[  125.256604]  ? preempt_count_sub+0xf/0xb0
[  125.256605]  ? _raw_spin_unlock+0x19/0x30
[  125.256607]  ? __alloc_fd+0x110/0x270
[  125.256609]  do_sys_open+0x1fb/0x2f0
[  125.256610]  ? filp_open+0x50/0x50
[  125.256613]  do_syscall_64+0x5e/0x190
[  125.256615]  entry_SYSCALL_64_after_hwframe+0x44/0xa9
[  125.256617] RIP: 0033:0x73dc99750972
[  125.256619] Code: 00 00 85 c0 74 95 44 89 54 24 0c e8 48 f2 ff ff 44 8b 54 24 0c 44 89 e2 48 89 ee 41 89 c0 bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d 00 f0 ff ff 77 2c 44 89 c7 89 44 24 0c e8 7a f2 ff ff 8b 44
[  125.256620] RSP: 002b:000073dc837fd230 EFLAGS: 00000293 ORIG_RAX: 0000000000000101
[  125.256622] RAX: ffffffffffffffda RBX: 000073dc837fd340 RCX: 000073dc99750972
[  125.256623] RDX: 0000000000000002 RSI: 000073dc7401e430 RDI: 00000000ffffff9c
[  125.256624] RBP: 000073dc7401e430 R08: 0000000000000000 R09: 000073dc7401b300
[  125.256625] R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000000002
[  125.256626] R13: 000073dc7401ee60 R14: 000000000000000a R15: 000073dc3c09a910

[  125.256629] Allocated by task 3749:
[  125.256630]  save_stack+0x20/0x80
[  125.256632]  __kasan_kmalloc.constprop.0+0xc3/0xd0
[  125.256633]  __kmalloc+0x151/0x2e0
[  125.256635]  sk_prot_alloc+0x10b/0x1c0
[  125.256636]  sk_alloc+0x2b/0x370
[  125.256637]  tap_open+0x11c/0x580
[  125.256639]  chrdev_open+0x171/0x380
[  125.256640]  do_dentry_open+0x2dd/0x7f0
[  125.256641]  path_openat+0x94f/0x22e0
[  125.256642]  do_filp_open+0x110/0x1a0
[  125.256644]  do_sys_open+0x1fb/0x2f0
[  125.256645]  do_syscall_64+0x5e/0x190
[  125.256646]  entry_SYSCALL_64_after_hwframe+0x44/0xa9

[  125.256647] Freed by task 4309:
[  125.256649]  save_stack+0x20/0x80
[  125.256650]  __kasan_slab_free+0x12c/0x170
[  125.256651]  kfree+0xa5/0x230
[  125.256653]  alloc_iova_fast+0x2bb/0x380
[  125.256656]  intel_alloc_iova+0xad/0xc0
[  125.256657]  intel_map_sg+0xe0/0x210
[  125.256659]  ata_qc_issue+0x4aa/0x4c0
[  125.256661]  ata_scsi_translate+0x1b0/0x2c0
[  125.256663]  ata_scsi_queuecmd+0x13f/0x400
[  125.256664]  scsi_queue_rq+0xbed/0xf00
[  125.256667]  __blk_mq_try_issue_directly+0x263/0x380
[  125.256668]  blk_mq_try_issue_directly+0x81/0xf0
[  125.256670]  blk_mq_make_request+0x5fe/0x770
[  125.256672]  generic_make_request+0x176/0x530
[  125.256673]  submit_bio+0x9f/0x260
[  125.256676]  submit_bh_wbc+0x348/0x380
[  125.256677]  ll_rw_block+0x123/0x130
[  125.256679]  __breadahead+0x91/0xe0
[  125.256681]  __ext4_get_inode_loc+0x65e/0x720
[  125.256682]  __ext4_iget+0x1ff/0x1980
[  125.256684]  ext4_lookup+0x21a/0x380
[  125.256686]  path_openat+0xae2/0x22e0
[  125.256687]  do_filp_open+0x110/0x1a0
[  125.256688]  do_sys_open+0x1fb/0x2f0
[  125.256689]  do_syscall_64+0x5e/0x190
[  125.256690]  entry_SYSCALL_64_after_hwframe+0x44/0xa9

[  125.256692] The buggy address belongs to the object at ffff8887d1825468
                which belongs to the cache kmalloc-2k of size 2048
[  125.256694] The buggy address is located 1472 bytes inside of
                2048-byte region [ffff8887d1825468, ffff8887d1825c68)
[  125.256694] The buggy address belongs to the page:
[  125.256696] page:ffffea001f460800 refcount:1 mapcount:0 mapping:ffff8887db0113c0 index:0x0 compound_mapcount: 0
[  125.256698] flags: 0x200000000010200(slab|head)
[  125.256701] raw: 0200000000010200 ffffea001d55a008 ffff8887db003470 ffff8887db0113c0
[  125.256703] raw: 0000000000000000 00000000000d000d 00000001ffffffff 0000000000000000
[  125.256703] page dumped because: kasan: bad access detected

[  125.256704] Memory state around the buggy address:
[  125.256706]  ffff8887d1825900: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  125.256707]  ffff8887d1825980: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  125.256708] >ffff8887d1825a00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  125.256709]                                   ^
[  125.256710]  ffff8887d1825a80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  125.256712]  ffff8887d1825b00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
[  125.256712] ==================================================================
[  125.256713] Disabling lock debugging due to kernel taint

From my investigation it happen because of:
		sk->sk_uid	=	SOCK_INODE(sock)->i_uid;
in sock_init_data().

From this it seems quite obvious that sock_init_data() actually expects
passed  sock  argument to be allocated with sock_alloc.

Following patches are attempt to fix this by using sock_alloc(), it
seems to work fine on my system, but I'm not that well versed on
networking internals.

Few points of doubt:
 * TAP & TUN apparently just need, sock without inode, so doing
sock_alloc doesn't seem that good
 * As far as I understand an API I should put sock_release somewhere,
but if I put it in places that seem logical to me it causes oops on null
pointer, does network API free scoket automatically somewhere?
 * Maybe it is just simpler and more error proof to add some flag inside
sock_alloc, so it knows that it can do SOCK_INODE call...

Cheers,
Amadeusz


Amadeusz Sławiński (2):
  net: tap: Fix incorrect memory access
  net: tun: Fix incorrect memory access

 drivers/net/tap.c      | 34 ++++++++++------
 drivers/net/tun.c      | 92 +++++++++++++++++++++++-------------------
 include/linux/if_tap.h |  2 +-
 3 files changed, 72 insertions(+), 56 deletions(-)

-- 
2.23.0


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [RFC PATCH 1/2] net: tap: Fix incorrect memory access
  2019-09-29 11:05 [RFC PATCH 0/2] Incorrect memory access when using TAP Amadeusz Sławiński
@ 2019-09-29 11:05 ` Amadeusz Sławiński
  2019-09-29 11:05 ` [RFC PATCH 2/2] net: tun: " Amadeusz Sławiński
  1 sibling, 0 replies; 3+ messages in thread
From: Amadeusz Sławiński @ 2019-09-29 11:05 UTC (permalink / raw)
  To: David S . Miller, netdev; +Cc: Amadeusz Sławiński

KASAN reported incorrect memory access when sock_init_data() was called.
This happens due to the fact that if sock_init_data() is called with
sock argument being not NULL, it goes into path using SOCK_INODE macro.
SOCK_INODE itself is just a wrapper around
container_of(socket, struct socket_alloc, socket).

As can be seen from that flow sock_init_data, should be called with
sock, being part of struct socket_alloc, instead of being part of
struct tap_queue.

Refactor code to follow flow similar in other places where sock is
allocated correctly.

Signed-off-by: Amadeusz Sławiński <amade@asmblr.net>
---
 drivers/net/tap.c      | 34 +++++++++++++++++++++-------------
 include/linux/if_tap.h |  2 +-
 2 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index dd614c2cd994..d1f59bad599f 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -501,6 +501,7 @@ static void tap_sock_destruct(struct sock *sk)
 static int tap_open(struct inode *inode, struct file *file)
 {
 	struct net *net = current->nsproxy->net_ns;
+	struct socket *sock;
 	struct tap_dev *tap;
 	struct tap_queue *q;
 	int err = -ENODEV;
@@ -515,17 +516,25 @@ static int tap_open(struct inode *inode, struct file *file)
 					     &tap_proto, 0);
 	if (!q)
 		goto err;
+
+	sock = sock_alloc();
+	if (!sock) {
+		sk_free(&q->sk);
+		goto err;
+	}
+	q->sock = sock;
+
 	if (ptr_ring_init(&q->ring, tap->dev->tx_queue_len, GFP_KERNEL)) {
+		sock_release(q->sock);
 		sk_free(&q->sk);
 		goto err;
 	}
 
-	init_waitqueue_head(&q->sock.wq.wait);
-	q->sock.type = SOCK_RAW;
-	q->sock.state = SS_CONNECTED;
-	q->sock.file = file;
-	q->sock.ops = &tap_socket_ops;
-	sock_init_data(&q->sock, &q->sk);
+	sock->type = SOCK_RAW;
+	sock->state = SS_CONNECTED;
+	sock->file = file;
+	sock->ops = &tap_socket_ops;
+	sock_init_data(sock, &q->sk);
 	q->sk.sk_write_space = tap_sock_write_space;
 	q->sk.sk_destruct = tap_sock_destruct;
 	q->flags = IFF_VNET_HDR | IFF_NO_PI | IFF_TAP;
@@ -578,13 +587,13 @@ static __poll_t tap_poll(struct file *file, poll_table *wait)
 		goto out;
 
 	mask = 0;
-	poll_wait(file, &q->sock.wq.wait, wait);
+	poll_wait(file, &q->sock->wq.wait, wait);
 
 	if (!ptr_ring_empty(&q->ring))
 		mask |= EPOLLIN | EPOLLRDNORM;
 
 	if (sock_writeable(&q->sk) ||
-	    (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &q->sock.flags) &&
+	    (!test_and_set_bit(SOCKWQ_ASYNC_NOSPACE, &q->sock->flags) &&
 	     sock_writeable(&q->sk)))
 		mask |= EPOLLOUT | EPOLLWRNORM;
 
@@ -1210,7 +1219,7 @@ static int tap_get_user_xdp(struct tap_queue *q, struct xdp_buff *xdp)
 static int tap_sendmsg(struct socket *sock, struct msghdr *m,
 		       size_t total_len)
 {
-	struct tap_queue *q = container_of(sock, struct tap_queue, sock);
+	struct tap_queue *q = container_of(sock->sk, struct tap_queue, sk);
 	struct tun_msg_ctl *ctl = m->msg_control;
 	struct xdp_buff *xdp;
 	int i;
@@ -1230,7 +1239,7 @@ static int tap_sendmsg(struct socket *sock, struct msghdr *m,
 static int tap_recvmsg(struct socket *sock, struct msghdr *m,
 		       size_t total_len, int flags)
 {
-	struct tap_queue *q = container_of(sock, struct tap_queue, sock);
+	struct tap_queue *q = container_of(sock->sk, struct tap_queue, sk);
 	struct sk_buff *skb = m->msg_control;
 	int ret;
 	if (flags & ~(MSG_DONTWAIT|MSG_TRUNC)) {
@@ -1247,8 +1256,7 @@ static int tap_recvmsg(struct socket *sock, struct msghdr *m,
 
 static int tap_peek_len(struct socket *sock)
 {
-	struct tap_queue *q = container_of(sock, struct tap_queue,
-					       sock);
+	struct tap_queue *q = container_of(sock->sk, struct tap_queue, sk);
 	return PTR_RING_PEEK_CALL(&q->ring, __skb_array_len_with_tag);
 }
 
@@ -1271,7 +1279,7 @@ struct socket *tap_get_socket(struct file *file)
 	q = file->private_data;
 	if (!q)
 		return ERR_PTR(-EBADFD);
-	return &q->sock;
+	return q->sock;
 }
 EXPORT_SYMBOL_GPL(tap_get_socket);
 
diff --git a/include/linux/if_tap.h b/include/linux/if_tap.h
index 915a187cfabd..60d00609d6ed 100644
--- a/include/linux/if_tap.h
+++ b/include/linux/if_tap.h
@@ -61,7 +61,7 @@ struct tap_dev {
 
 struct tap_queue {
 	struct sock sk;
-	struct socket sock;
+	struct socket *sock;
 	int vnet_hdr_sz;
 	struct tap_dev __rcu *tap;
 	struct file *file;
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* [RFC PATCH 2/2] net: tun: Fix incorrect memory access
  2019-09-29 11:05 [RFC PATCH 0/2] Incorrect memory access when using TAP Amadeusz Sławiński
  2019-09-29 11:05 ` [RFC PATCH 1/2] net: tap: Fix incorrect memory access Amadeusz Sławiński
@ 2019-09-29 11:05 ` Amadeusz Sławiński
  1 sibling, 0 replies; 3+ messages in thread
From: Amadeusz Sławiński @ 2019-09-29 11:05 UTC (permalink / raw)
  To: David S . Miller, netdev; +Cc: Amadeusz Sławiński

This is equivalent commit to tap one, where we fix incorrect memory
access caused by sock_init_data being passed improper socket.

This happens due to the fact that if sock_init_data() is called with
sock argument being not NULL, it goes into path using SOCK_INODE macro.
SOCK_INODE itself is just a wrapper around
container_of(socket, struct socket_alloc, socket).

As can be seen from that flow sock_init_data, should be called with
sock, being part of struct socket_alloc, instead of being part of
struct tun_file.

Refactor code to follow flow similar in other places where sock is
allocated correctly.

Signed-off-by: Amadeusz Sławiński <amade@asmblr.net>
---
 drivers/net/tun.c | 92 +++++++++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 42 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index aab0be40d443..60344794579c 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -159,7 +159,7 @@ struct tun_pcpu_stats {
  */
 struct tun_file {
 	struct sock sk;
-	struct socket socket;
+	struct socket *socket;
 	struct tun_struct __rcu *tun;
 	struct fasync_struct *fasync;
 	/* only used for fasnyc */
@@ -753,14 +753,14 @@ static void tun_detach_all(struct net_device *dev)
 		tfile = rtnl_dereference(tun->tfiles[i]);
 		BUG_ON(!tfile);
 		tun_napi_disable(tfile);
-		tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN;
-		tfile->socket.sk->sk_data_ready(tfile->socket.sk);
+		tfile->socket->sk->sk_shutdown = RCV_SHUTDOWN;
+		tfile->socket->sk->sk_data_ready(tfile->socket->sk);
 		RCU_INIT_POINTER(tfile->tun, NULL);
 		--tun->numqueues;
 	}
 	list_for_each_entry(tfile, &tun->disabled, next) {
-		tfile->socket.sk->sk_shutdown = RCV_SHUTDOWN;
-		tfile->socket.sk->sk_data_ready(tfile->socket.sk);
+		tfile->socket->sk->sk_shutdown = RCV_SHUTDOWN;
+		tfile->socket->sk->sk_data_ready(tfile->socket->sk);
 		RCU_INIT_POINTER(tfile->tun, NULL);
 	}
 	BUG_ON(tun->numqueues != 0);
@@ -794,7 +794,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
 	struct net_device *dev = tun->dev;
 	int err;
 
-	err = security_tun_dev_attach(tfile->socket.sk, tun->security);
+	err = security_tun_dev_attach(tfile->socket->sk, tun->security);
 	if (err < 0)
 		goto out;
 
@@ -815,9 +815,9 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
 
 	/* Re-attach the filter to persist device */
 	if (!skip_filter && (tun->filter_attached == true)) {
-		lock_sock(tfile->socket.sk);
-		err = sk_attach_filter(&tun->fprog, tfile->socket.sk);
-		release_sock(tfile->socket.sk);
+		lock_sock(tfile->socket->sk);
+		err = sk_attach_filter(&tun->fprog, tfile->socket->sk);
+		release_sock(tfile->socket->sk);
 		if (!err)
 			goto out;
 	}
@@ -830,7 +830,7 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
 	}
 
 	tfile->queue_index = tun->numqueues;
-	tfile->socket.sk->sk_shutdown &= ~RCV_SHUTDOWN;
+	tfile->socket->sk->sk_shutdown &= ~RCV_SHUTDOWN;
 
 	if (tfile->detached) {
 		/* Re-attach detached tfile, updating XDP queue_index */
@@ -1086,8 +1086,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 	if (!check_filter(&tun->txflt, skb))
 		goto drop;
 
-	if (tfile->socket.sk->sk_filter &&
-	    sk_filter(tfile->socket.sk, skb))
+	if (tfile->socket->sk->sk_filter &&
+	    sk_filter(tfile->socket->sk, skb))
 		goto drop;
 
 	len = run_ebpf_filter(tun, skb, len);
@@ -1112,7 +1112,7 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev)
 	/* Notify and wake up reader process */
 	if (tfile->flags & TUN_FASYNC)
 		kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
-	tfile->socket.sk->sk_data_ready(tfile->socket.sk);
+	tfile->socket->sk->sk_data_ready(tfile->socket->sk);
 
 	rcu_read_unlock();
 	return NETDEV_TX_OK;
@@ -1275,7 +1275,7 @@ static void __tun_xdp_flush_tfile(struct tun_file *tfile)
 	/* Notify and wake up reader process */
 	if (tfile->flags & TUN_FASYNC)
 		kill_fasync(&tfile->fasync, SIGIO, POLL_IN);
-	tfile->socket.sk->sk_data_ready(tfile->socket.sk);
+	tfile->socket->sk->sk_data_ready(tfile->socket->sk);
 }
 
 static int tun_xdp_xmit(struct net_device *dev, int n,
@@ -1415,7 +1415,7 @@ static void tun_net_init(struct net_device *dev)
 
 static bool tun_sock_writeable(struct tun_struct *tun, struct tun_file *tfile)
 {
-	struct sock *sk = tfile->socket.sk;
+	struct sock *sk = tfile->socket->sk;
 
 	return (tun->dev->flags & IFF_UP) && sock_writeable(sk);
 }
@@ -1433,7 +1433,7 @@ static __poll_t tun_chr_poll(struct file *file, poll_table *wait)
 	if (!tun)
 		return EPOLLERR;
 
-	sk = tfile->socket.sk;
+	sk = tfile->socket->sk;
 
 	tun_debug(KERN_INFO, tun, "tun_chr_poll\n");
 
@@ -1518,7 +1518,7 @@ static struct sk_buff *tun_alloc_skb(struct tun_file *tfile,
 				     size_t prepad, size_t len,
 				     size_t linear, int noblock)
 {
-	struct sock *sk = tfile->socket.sk;
+	struct sock *sk = tfile->socket->sk;
 	struct sk_buff *skb;
 	int err;
 
@@ -1585,7 +1585,7 @@ static bool tun_can_build_skb(struct tun_struct *tun, struct tun_file *tfile,
 	if ((tun->flags & TUN_TYPE_MASK) != IFF_TAP)
 		return false;
 
-	if (tfile->socket.sk->sk_sndbuf != INT_MAX)
+	if (tfile->socket->sk->sk_sndbuf != INT_MAX)
 		return false;
 
 	if (!noblock)
@@ -1612,7 +1612,7 @@ static struct sk_buff *__tun_build_skb(struct tun_file *tfile,
 
 	skb_reserve(skb, pad);
 	skb_put(skb, len);
-	skb_set_owner_w(skb, tfile->socket.sk);
+	skb_set_owner_w(skb, tfile->socket->sk);
 
 	get_page(alloc_frag->page);
 	alloc_frag->offset += buflen;
@@ -2169,7 +2169,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
 		goto out;
 	}
 
-	add_wait_queue(&tfile->socket.wq.wait, &wait);
+	add_wait_queue(&tfile->socket->wq.wait, &wait);
 
 	while (1) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -2180,7 +2180,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
 			error = -ERESTARTSYS;
 			break;
 		}
-		if (tfile->socket.sk->sk_shutdown & RCV_SHUTDOWN) {
+		if (tfile->socket->sk->sk_shutdown & RCV_SHUTDOWN) {
 			error = -EFAULT;
 			break;
 		}
@@ -2189,7 +2189,7 @@ static void *tun_ring_recv(struct tun_file *tfile, int noblock, int *err)
 	}
 
 	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&tfile->socket.wq.wait, &wait);
+	remove_wait_queue(&tfile->socket->wq.wait, &wait);
 
 out:
 	*err = error;
@@ -2519,7 +2519,7 @@ static int tun_xdp_one(struct tun_struct *tun,
 static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
 {
 	int ret, i;
-	struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+	struct tun_file *tfile = container_of(sock->sk, struct tun_file, sk);
 	struct tun_struct *tun = tun_get(tfile);
 	struct tun_msg_ctl *ctl = m->msg_control;
 	struct xdp_buff *xdp;
@@ -2565,7 +2565,7 @@ static int tun_sendmsg(struct socket *sock, struct msghdr *m, size_t total_len)
 static int tun_recvmsg(struct socket *sock, struct msghdr *m, size_t total_len,
 		       int flags)
 {
-	struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+	struct tun_file *tfile = container_of(sock->sk, struct tun_file, sk);
 	struct tun_struct *tun = tun_get(tfile);
 	void *ptr = m->msg_control;
 	int ret;
@@ -2616,7 +2616,7 @@ static int tun_ptr_peek_len(void *ptr)
 
 static int tun_peek_len(struct socket *sock)
 {
-	struct tun_file *tfile = container_of(sock, struct tun_file, socket);
+	struct tun_file *tfile = container_of(sock->sk, struct tun_file, sk);
 	struct tun_struct *tun;
 	int ret = 0;
 
@@ -2799,7 +2799,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
 		tun->align = NET_SKB_PAD;
 		tun->filter_attached = false;
-		tun->sndbuf = tfile->socket.sk->sk_sndbuf;
+		tun->sndbuf = tfile->socket->sk->sk_sndbuf;
 		tun->rx_batched = 0;
 		RCU_INIT_POINTER(tun->steering_prog, NULL);
 
@@ -2927,9 +2927,9 @@ static void tun_detach_filter(struct tun_struct *tun, int n)
 
 	for (i = 0; i < n; i++) {
 		tfile = rtnl_dereference(tun->tfiles[i]);
-		lock_sock(tfile->socket.sk);
-		sk_detach_filter(tfile->socket.sk);
-		release_sock(tfile->socket.sk);
+		lock_sock(tfile->socket->sk);
+		sk_detach_filter(tfile->socket->sk);
+		release_sock(tfile->socket->sk);
 	}
 
 	tun->filter_attached = false;
@@ -2942,9 +2942,9 @@ static int tun_attach_filter(struct tun_struct *tun)
 
 	for (i = 0; i < tun->numqueues; i++) {
 		tfile = rtnl_dereference(tun->tfiles[i]);
-		lock_sock(tfile->socket.sk);
-		ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);
-		release_sock(tfile->socket.sk);
+		lock_sock(tfile->socket->sk);
+		ret = sk_attach_filter(&tun->fprog, tfile->socket->sk);
+		release_sock(tfile->socket->sk);
 		if (ret) {
 			tun_detach_filter(tun, i);
 			return ret;
@@ -2962,7 +2962,7 @@ static void tun_set_sndbuf(struct tun_struct *tun)
 
 	for (i = 0; i < tun->numqueues; i++) {
 		tfile = rtnl_dereference(tun->tfiles[i]);
-		tfile->socket.sk->sk_sndbuf = tun->sndbuf;
+		tfile->socket->sk->sk_sndbuf = tun->sndbuf;
 	}
 }
 
@@ -3109,7 +3109,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 
 		if (tfile->detached)
 			ifr.ifr_flags |= IFF_DETACH_QUEUE;
-		if (!tfile->socket.sk->sk_filter)
+		if (!tfile->socket->sk->sk_filter)
 			ifr.ifr_flags |= IFF_NOFILTER;
 
 		if (copy_to_user(argp, &ifr, ifreq_len))
@@ -3217,7 +3217,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
 		break;
 
 	case TUNGETSNDBUF:
-		sndbuf = tfile->socket.sk->sk_sndbuf;
+		sndbuf = tfile->socket->sk->sk_sndbuf;
 		if (copy_to_user(argp, &sndbuf, sizeof(sndbuf)))
 			ret = -EFAULT;
 		break;
@@ -3405,6 +3405,7 @@ static int tun_chr_fasync(int fd, struct file *file, int on)
 static int tun_chr_open(struct inode *inode, struct file * file)
 {
 	struct net *net = current->nsproxy->net_ns;
+	struct socket *sock;
 	struct tun_file *tfile;
 
 	DBG1(KERN_INFO, "tunX: tun_chr_open\n");
@@ -3413,7 +3414,16 @@ static int tun_chr_open(struct inode *inode, struct file * file)
 					    &tun_proto, 0);
 	if (!tfile)
 		return -ENOMEM;
+
+	sock = sock_alloc();
+	if (!sock) {
+		sk_free(&tfile->sk);
+		return -ENOMEM;
+	}
+	tfile->socket = sock;
+
 	if (ptr_ring_init(&tfile->tx_ring, 0, GFP_KERNEL)) {
+		sock_release(tfile->socket);
 		sk_free(&tfile->sk);
 		return -ENOMEM;
 	}
@@ -3423,12 +3433,10 @@ static int tun_chr_open(struct inode *inode, struct file * file)
 	tfile->flags = 0;
 	tfile->ifindex = 0;
 
-	init_waitqueue_head(&tfile->socket.wq.wait);
-
-	tfile->socket.file = file;
-	tfile->socket.ops = &tun_socket_ops;
+	sock->file = file;
+	sock->ops = &tun_socket_ops;
 
-	sock_init_data(&tfile->socket, &tfile->sk);
+	sock_init_data(sock, &tfile->sk);
 
 	tfile->sk.sk_write_space = tun_sock_write_space;
 	tfile->sk.sk_sndbuf = INT_MAX;
@@ -3646,7 +3654,7 @@ static int tun_device_event(struct notifier_block *unused,
 			struct tun_file *tfile;
 
 			tfile = rtnl_dereference(tun->tfiles[i]);
-			tfile->socket.sk->sk_write_space(tfile->socket.sk);
+			tfile->socket->sk->sk_write_space(tfile->socket->sk);
 		}
 		break;
 	default:
@@ -3713,7 +3721,7 @@ struct socket *tun_get_socket(struct file *file)
 	tfile = file->private_data;
 	if (!tfile)
 		return ERR_PTR(-EBADFD);
-	return &tfile->socket;
+	return tfile->socket;
 }
 EXPORT_SYMBOL_GPL(tun_get_socket);
 
-- 
2.23.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-09-29 12:10 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-09-29 11:05 [RFC PATCH 0/2] Incorrect memory access when using TAP Amadeusz Sławiński
2019-09-29 11:05 ` [RFC PATCH 1/2] net: tap: Fix incorrect memory access Amadeusz Sławiński
2019-09-29 11:05 ` [RFC PATCH 2/2] net: tun: " Amadeusz Sławiński

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).