Unverified Commit eafc34bb authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!2573 media: dvb-core: Fix use-after-free due to race condition at dvb_ca_en50221

parents 648197ad daf0f675
Loading
Loading
Loading
Loading
+36 −1
Original line number Diff line number Diff line
@@ -151,6 +151,12 @@ struct dvb_ca_private {

	/* mutex serializing ioctls */
	struct mutex ioctl_mutex;

	/* A mutex used when a device is disconnected */
	struct mutex remove_mutex;

	/* Whether the device is disconnected */
	int exit;
};

static void dvb_ca_private_free(struct dvb_ca_private *ca)
@@ -1706,12 +1712,22 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)

	dprintk("%s\n", __func__);

	if (!try_module_get(ca->pub->owner))
	mutex_lock(&ca->remove_mutex);

	if (ca->exit) {
		mutex_unlock(&ca->remove_mutex);
		return -ENODEV;
	}

	if (!try_module_get(ca->pub->owner)) {
		mutex_unlock(&ca->remove_mutex);
		return -EIO;
	}

	err = dvb_generic_open(inode, file);
	if (err < 0) {
		module_put(ca->pub->owner);
		mutex_unlock(&ca->remove_mutex);
		return err;
	}

@@ -1736,6 +1752,7 @@ static int dvb_ca_en50221_io_open(struct inode *inode, struct file *file)

	dvb_ca_private_get(ca);

	mutex_unlock(&ca->remove_mutex);
	return 0;
}

@@ -1755,6 +1772,8 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)

	dprintk("%s\n", __func__);

	mutex_lock(&ca->remove_mutex);

	/* mark the CA device as closed */
	ca->open = 0;
	dvb_ca_en50221_thread_update_delay(ca);
@@ -1765,6 +1784,13 @@ static int dvb_ca_en50221_io_release(struct inode *inode, struct file *file)

	dvb_ca_private_put(ca);

	if (dvbdev->users == 1 && ca->exit == 1) {
		mutex_unlock(&ca->remove_mutex);
		wake_up(&dvbdev->wait_queue);
	} else {
		mutex_unlock(&ca->remove_mutex);
	}

	return err;
}

@@ -1888,6 +1914,7 @@ int dvb_ca_en50221_init(struct dvb_adapter *dvb_adapter,
	}

	mutex_init(&ca->ioctl_mutex);
	mutex_init(&ca->remove_mutex);

	if (signal_pending(current)) {
		ret = -EINTR;
@@ -1930,6 +1957,14 @@ void dvb_ca_en50221_release(struct dvb_ca_en50221 *pubca)

	dprintk("%s\n", __func__);

	mutex_lock(&ca->remove_mutex);
	ca->exit = 1;
	mutex_unlock(&ca->remove_mutex);

	if (ca->dvbdev->users < 1)
		wait_event(ca->dvbdev->wait_queue,
				ca->dvbdev->users == 1);

	/* shutdown the thread if there was one */
	kthread_stop(ca->thread);