forked from rubenslte/android_kernel_samsung_msm8226
msm: camera: Instead of read_lock use read_lock_irqsave.
Prevent deadlock between tasklet and delete_stream by stopping irq during delete_stream. CRs-Fixed: 2076578 Change-Id: Ibcc9fd44403d24112b01150a7d1f3c6e705ea99a Signed-off-by: Trishansh Bhardwaj <tbhardwa@codeaurora.org> Signed-off-by: VijayaKumar T M <vtmuni@codeaurora.org> CVE-2017-9704 Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
This commit is contained in:
committed by
matteo0026
parent
c7dfc3df1d
commit
17cad8e6a8
@@ -258,6 +258,7 @@ void msm_delete_stream(unsigned int session_id, unsigned int stream_id)
|
||||
return;
|
||||
|
||||
while (1) {
|
||||
unsigned long wl_flags;
|
||||
|
||||
if (try_count > 5) {
|
||||
pr_err("%s : not able to delete stream %d\n",
|
||||
@@ -265,18 +266,20 @@ void msm_delete_stream(unsigned int session_id, unsigned int stream_id)
|
||||
break;
|
||||
}
|
||||
|
||||
write_lock(&session->stream_rwlock);
|
||||
write_lock_irqsave(&session->stream_rwlock, wl_flags);
|
||||
try_count++;
|
||||
stream = msm_queue_find(&session->stream_q, struct msm_stream,
|
||||
list, __msm_queue_find_stream, &stream_id);
|
||||
|
||||
if (!stream) {
|
||||
write_unlock(&session->stream_rwlock);
|
||||
write_unlock_irqrestore(&session->stream_rwlock,
|
||||
wl_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
if (msm_vb2_get_stream_state(stream) != 1) {
|
||||
write_unlock(&session->stream_rwlock);
|
||||
write_unlock_irqrestore(&session->stream_rwlock,
|
||||
wl_flags);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -286,7 +289,7 @@ void msm_delete_stream(unsigned int session_id, unsigned int stream_id)
|
||||
kzfree(stream);
|
||||
stream = NULL;
|
||||
spin_unlock_irqrestore(&(session->stream_q.lock), flags);
|
||||
write_unlock(&session->stream_rwlock);
|
||||
write_unlock_irqrestore(&session->stream_rwlock, wl_flags);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,22 +42,23 @@ int msm_vb2_buf_init(struct vb2_buffer *vb)
|
||||
struct msm_stream *stream;
|
||||
struct msm_session *session;
|
||||
struct msm_vb2_buffer *msm_vb2_buf;
|
||||
unsigned long rl_flags;
|
||||
|
||||
session = msm_get_session_from_vb2q(vb->vb2_queue);
|
||||
if (IS_ERR_OR_NULL(session))
|
||||
return -EINVAL;
|
||||
|
||||
read_lock(&session->stream_rwlock);
|
||||
read_lock_irqsave(&session->stream_rwlock, rl_flags);
|
||||
|
||||
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
||||
if (!stream) {
|
||||
pr_err("%s: Couldn't find stream\n", __func__);
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
msm_vb2_buf = container_of(vb, struct msm_vb2_buffer, vb2_buf);
|
||||
msm_vb2_buf->in_freeq = 0;
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -66,7 +67,7 @@ static void msm_vb2_buf_queue(struct vb2_buffer *vb)
|
||||
struct msm_vb2_buffer *msm_vb2;
|
||||
struct msm_stream *stream;
|
||||
struct msm_session *session;
|
||||
unsigned long flags;
|
||||
unsigned long flags, rl_flags;
|
||||
|
||||
msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf);
|
||||
|
||||
@@ -79,19 +80,19 @@ static void msm_vb2_buf_queue(struct vb2_buffer *vb)
|
||||
if (IS_ERR_OR_NULL(session))
|
||||
return;
|
||||
|
||||
read_lock(&session->stream_rwlock);
|
||||
read_lock_irqsave(&session->stream_rwlock, rl_flags);
|
||||
|
||||
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
||||
if (!stream) {
|
||||
pr_err("%s:%d] NULL stream", __func__, __LINE__);
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&stream->stream_lock, flags);
|
||||
list_add_tail(&msm_vb2->list, &stream->queued_list);
|
||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
}
|
||||
|
||||
static int msm_vb2_buf_finish(struct vb2_buffer *vb)
|
||||
@@ -99,7 +100,7 @@ static int msm_vb2_buf_finish(struct vb2_buffer *vb)
|
||||
struct msm_vb2_buffer *msm_vb2;
|
||||
struct msm_stream *stream;
|
||||
struct msm_session *session;
|
||||
unsigned long flags;
|
||||
unsigned long flags, rl_flags;
|
||||
struct msm_vb2_buffer *msm_vb2_entry, *temp;
|
||||
|
||||
msm_vb2 = container_of(vb, struct msm_vb2_buffer, vb2_buf);
|
||||
@@ -113,12 +114,12 @@ static int msm_vb2_buf_finish(struct vb2_buffer *vb)
|
||||
if (IS_ERR_OR_NULL(session))
|
||||
return -EINVAL;
|
||||
|
||||
read_lock(&session->stream_rwlock);
|
||||
read_lock_irqsave(&session->stream_rwlock, rl_flags);
|
||||
|
||||
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
|
||||
if (!stream) {
|
||||
pr_err("%s:%d] NULL stream", __func__, __LINE__);
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -131,7 +132,7 @@ static int msm_vb2_buf_finish(struct vb2_buffer *vb)
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -232,17 +233,17 @@ static struct vb2_buffer *msm_vb2_get_buf(int session_id,
|
||||
struct vb2_buffer *vb2_buf = NULL;
|
||||
struct msm_session *session;
|
||||
struct msm_vb2_buffer *msm_vb2 = NULL;
|
||||
unsigned long flags;
|
||||
unsigned long flags, rl_flags;
|
||||
|
||||
session = msm_get_session(session_id);
|
||||
if (IS_ERR_OR_NULL(session))
|
||||
return NULL;
|
||||
|
||||
read_lock(&session->stream_rwlock);
|
||||
read_lock_irqsave(&session->stream_rwlock, rl_flags);
|
||||
|
||||
stream = msm_get_stream(session, stream_id);
|
||||
if (IS_ERR_OR_NULL(stream)) {
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -268,7 +269,7 @@ static struct vb2_buffer *msm_vb2_get_buf(int session_id,
|
||||
vb2_buf = NULL;
|
||||
end:
|
||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return vb2_buf;
|
||||
}
|
||||
|
||||
@@ -279,17 +280,17 @@ static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id,
|
||||
struct msm_session *session;
|
||||
struct msm_vb2_buffer *msm_vb2;
|
||||
int rc = 0;
|
||||
unsigned long flags;
|
||||
unsigned long flags, rl_flags;
|
||||
|
||||
session = msm_get_session(session_id);
|
||||
if (IS_ERR_OR_NULL(session))
|
||||
return -EINVAL;
|
||||
|
||||
read_lock(&session->stream_rwlock);
|
||||
read_lock_irqsave(&session->stream_rwlock, rl_flags);
|
||||
|
||||
stream = msm_get_stream(session, stream_id);
|
||||
if (IS_ERR_OR_NULL(stream)) {
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -307,7 +308,7 @@ static int msm_vb2_put_buf(struct vb2_buffer *vb, int session_id,
|
||||
rc = -EINVAL;
|
||||
}
|
||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@@ -315,7 +316,7 @@ static int msm_vb2_buf_done(struct vb2_buffer *vb, int session_id,
|
||||
unsigned int stream_id, uint32_t sequence,
|
||||
struct timeval *ts, uint32_t reserved)
|
||||
{
|
||||
unsigned long flags;
|
||||
unsigned long flags, rl_flags;
|
||||
struct msm_vb2_buffer *msm_vb2;
|
||||
struct msm_stream *stream;
|
||||
struct vb2_buffer *vb2_buf = NULL;
|
||||
@@ -326,11 +327,11 @@ static int msm_vb2_buf_done(struct vb2_buffer *vb, int session_id,
|
||||
if (IS_ERR_OR_NULL(session))
|
||||
return -EINVAL;
|
||||
|
||||
read_lock(&session->stream_rwlock);
|
||||
read_lock_irqsave(&session->stream_rwlock, rl_flags);
|
||||
|
||||
stream = msm_get_stream(session, stream_id);
|
||||
if (IS_ERR_OR_NULL(stream)) {
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -365,7 +366,7 @@ buf_check_done:
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&stream->stream_lock, flags);
|
||||
read_unlock(&session->stream_rwlock);
|
||||
read_unlock_irqrestore(&session->stream_rwlock, rl_flags);
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user