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

Commit d9c78392 authored by Seemanta Dutta's avatar Seemanta Dutta
Browse files

msm: camera: sync: Flush work queue before close



When cam_sync_close() is called, make sure all pending
work queues have finished by flushing the work queue. This
will ensure that any callback structs that are freed while
destroying are not accessed by the work running in the queue.

Not doing so will result in a use after free when the work in
the work queue gets scheduled.

Change-Id: Ibf857026865e9ff7e8ea50acc29c06f2e1c05931
Signed-off-by: default avatarSeemanta Dutta <seemanta@codeaurora.org>
parent f531607d
Loading
Loading
Loading
Loading
+35 −13
Original line number Diff line number Diff line
@@ -790,21 +790,43 @@ static int cam_sync_close(struct file *filep)
		for (i = 1; i < CAM_SYNC_MAX_OBJS; i++) {
			struct sync_table_row *row =
			sync_dev->sync_table + i;
			if (row->state == CAM_SYNC_STATE_INVALID)
				continue;

			/* Signal all remaining objects as ERR,but we don't care
			 * about the return status here apart from logging it
			/*
			 * Signal all ACTIVE objects as ERR, but we don't
			 * care about the return status here apart from logging
			 * it.
			 */
			rc = cam_sync_signal(i, CAM_SYNC_STATE_SIGNALED_ERROR);
			if (row->state == CAM_SYNC_STATE_ACTIVE) {
				rc = cam_sync_signal(i,
					CAM_SYNC_STATE_SIGNALED_ERROR);
				if (rc < 0)
					CAM_ERR(CAM_SYNC,
					"Cleanup signal failed: idx = %d", i);
					  "Cleanup signal fail idx:%d\n",
					  i);
			}
		}

		/*
		 * Flush the work queue to wait for pending signal callbacks to
		 * finish
		 */
		flush_workqueue(sync_dev->work_queue);

		/*
		 * Now that all callbacks worker threads have finished,
		 * destroy the sync objects
		 */
		for (i = 1; i < CAM_SYNC_MAX_OBJS; i++) {
			struct sync_table_row *row =
			sync_dev->sync_table + i;

			if (row->state != CAM_SYNC_STATE_INVALID) {
				rc = cam_sync_destroy(i);
				if (rc < 0)
					CAM_ERR(CAM_SYNC,
					"Cleanup destroy failed: idx = %d", i);
					  "Cleanup destroy fail:idx:%d\n",
					  i);
			}
		}
	}
	mutex_unlock(&sync_dev->table_lock);