Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 257d632c authored by Hardik Arya's avatar Hardik Arya Committed by Manoj Prabhu B
Browse files

diag: Add protection while accessing socket info's handle



Currently, there is a possibility of passing invalid NULL handle
to selinux function after closing the channel. The patch adds
protection while accessing socket info's handle.

CRs-Fixed: 2111893
Change-Id: I94515cc52352446d61a710ed1c09818a78c39f46
Signed-off-by: default avatarHardik Arya <harya@codeaurora.org>
Signed-off-by: default avatarManoj Prabhu B <bmanoj@codeaurora.org>
parent 45eab650
Loading
Loading
Loading
Loading
+34 −3
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 */

#include <linux/slab.h>
@@ -511,9 +511,10 @@ static void __socket_close_channel(struct diag_socket_info *info)
	info->hdl->sk->sk_data_ready = NULL;
	info->hdl->sk->sk_error_report = NULL;
	write_unlock_bh(&info->hdl->sk->sk_callback_lock);
	mutex_lock(&info->socket_info_mutex);
	sock_release(info->hdl);
	info->hdl = NULL;

	mutex_unlock(&info->socket_info_mutex);
	cancel_work_sync(&info->read_work);
	wake_up_interruptible(&info->read_wait_q);

@@ -714,13 +715,28 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
		read_msg.msg_name = &src_addr;
		read_msg.msg_namelen = sizeof(src_addr);

		if (info->port_type != PORT_TYPE_SERVER) {
			mutex_lock(&info->socket_info_mutex);
			if (!info->hdl) {
				DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
				"%s closing read thread\n",
					info->name);
				mutex_unlock(&info->socket_info_mutex);
				goto fail;
			}
		}
		err =  info->hdl->ops->ioctl(info->hdl, TIOCINQ,
					(unsigned long)&pkt_len);
		if (err || pkt_len < 0)
		if (err || pkt_len < 0) {
			if (info->port_type != PORT_TYPE_SERVER)
				mutex_unlock(&info->socket_info_mutex);
			break;
		}

		if (pkt_len > bytes_remaining) {
			buf_full = 1;
			if (info->port_type != PORT_TYPE_SERVER)
				mutex_unlock(&info->socket_info_mutex);
			break;
		}

@@ -730,6 +746,8 @@ static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)

		read_len = kernel_recvmsg(info->hdl, &read_msg, &iov, 1,
					  pkt_len, MSG_DONTWAIT);
		if (info->port_type != PORT_TYPE_SERVER)
			mutex_unlock(&info->socket_info_mutex);
		if (unlikely(read_len == -ENETRESET)) {
			mutex_lock(channel_mutex);
			diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
@@ -837,7 +855,16 @@ static int diag_socket_write(void *ctxt, unsigned char *buf, int len)
	write_msg.msg_name = &info->remote_addr;
	write_msg.msg_namelen = sizeof(info->remote_addr);
	write_msg.msg_flags |= MSG_DONTWAIT;
	if (info->port_type != PORT_TYPE_SERVER) {
		mutex_lock(&info->socket_info_mutex);
		if (!info->hdl) {
			mutex_unlock(&info->socket_info_mutex);
			return -ENODEV;
		}
	}
	write_len = kernel_sendmsg(info->hdl, &write_msg, &iov, 1, len);
	if (info->port_type != PORT_TYPE_SERVER)
		mutex_unlock(&info->socket_info_mutex);
	if (write_len < 0) {
		err = write_len;
		/*
@@ -935,6 +962,8 @@ static void __diag_socket_init(struct diag_socket_info *info)
		break;
	}

	if (info->port_type == PORT_TYPE_CLIENT)
		mutex_init(&info->socket_info_mutex);
	info->svc_id = DIAG_SVC_ID;
	info->ins_id = ins_base + ins_offset;
	info->inited = 1;
@@ -1092,6 +1121,8 @@ static void __diag_socket_exit(struct diag_socket_info *info)
	if (info->hdl)
		sock_release(info->hdl);
	info->hdl = NULL;
	if (info->port_type == PORT_TYPE_CLIENT)
		mutex_destroy(&info->socket_info_mutex);
	if (info->wq)
		destroy_workqueue(info->wq);
}
+2 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2015-2019, The Linux Foundation. All rights reserved.
 */

#ifndef DIAGFWD_SOCKET_H
@@ -49,6 +49,7 @@ struct diag_socket_info {
	struct work_struct read_work;
	struct diagfwd_info *fwd_ctxt;
	wait_queue_head_t read_wait_q;
	struct mutex socket_info_mutex;
};