Package: asterisk / 1:1.6.2.9-2+squeeze12

AST-2012-008 Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
From: Matthew Jordan <mjordan@digium.com>
Date: Tue, 29 May 2012 18:30:25 +0000
Subject: [PATCH] AST-2012-008: remote crash issue in chan_skinny
Bug: https://issues.asterisk.org/jira/browse/ASTERISK-19905
Origin: http://svnview.digium.com/svn/asterisk?view=rev&rev=367843

When a skinny session is unregistered, the corresponding device pointer
is set to NULL in the channel private data.  If the client was not in
the on-hook state at the time the connection was closed, the device
pointer can later be dereferenced if a message or channel event attempts
to use a line's pointer to said device.

The patches prevent this from occurring by checking the line's pointer
in message handlers and channel callbacks that can fire after an
unregistration attempt.

Issue is only expoitable if you have an active Skinny (Cisco SCCP)
session. This implies you have a configured SCCP. If you have no idea
what this means: you don't. The default settings in Debian have no
configured Skinny devices.

See also: http://downloads.asterisk.org/pub/security/AST-2012-008.html

Adapted from patch to Asterisk 1.8 with minor changes.

---
 channels/chan_skinny.c |   44 ++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 40 insertions(+), 4 deletions(-)

diff --git a/channels/chan_skinny.c b/channels/chan_skinny.c
index 3abcbe3..4dbae9b 100644
--- a/channels/chan_skinny.c
+++ b/channels/chan_skinny.c
@@ -3633,6 +3633,11 @@ static void *skinny_ss(void *data)
 	int res = 0;
 	int loop_pause = 100;
 
+	if (!d) {
+		ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
+		return NULL;
+	}
+
 	ast_verb(3, "Starting simple switch on '%s@%s'\n", l->name, d->name);
 
 	len = strlen(d->exten);
@@ -3734,7 +3739,7 @@ static int skinny_call(struct ast_channel *ast, char *dest, int timeout)
 	struct skinny_line *l = sub->parent;
 	struct skinny_device *d = l->device;
 
-	if (!d->registered) {
+	if (!d || !d->registered) {
 		ast_log(LOG_ERROR, "Device not registered, cannot call %s\n", dest);
 		return -1;
 	}
@@ -3799,6 +3804,11 @@ static int skinny_hangup(struct ast_channel *ast)
 	d = l->device;
 	s = d->session;
 
+	if (!d) {
+		ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
+		return 0;
+	}
+
 	if (skinnydebug)
 		ast_verb(3,"Hanging up %s/%d\n",d->name,sub->callid);
 
@@ -4177,7 +4187,13 @@ static int skinny_indicate(struct ast_channel *ast, int ind, const void *data, s
 	struct skinny_subchannel *sub = ast->tech_pvt;
 	struct skinny_line *l = sub->parent;
 	struct skinny_device *d = l->device;
-	struct skinnysession *s = d->session;
+	struct skinnysession *s;
+
+	if (!d) {
+		ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
+		return -1;
+	}
+	s = d->session;
 
 	if (!s) {
 		ast_log(LOG_NOTICE, "Asked to indicate '%s' condition on channel %s, but session does not exist.\n", control2str(ind), ast->name);
@@ -4389,8 +4405,13 @@ static int skinny_hold(struct skinny_subchannel *sub)
 	struct skinny_device *d = l->device;
 
 	/* Don't try to hold a channel that doesn't exist */
-	if (!sub || !sub->owner)
+	if (!sub || !sub->owner) {
+		return 0;
+	}
+	if (!d) {
+		ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
 		return 0;
+	}
 
 	/* Channel needs to be put on hold */
 	if (skinnydebug)
@@ -4416,8 +4437,13 @@ static int skinny_unhold(struct skinny_subchannel *sub)
 	struct skinny_device *d = l->device;
 
 	/* Don't try to unhold a channel that doesn't exist */
-	if (!sub || !sub->owner)
+	if (!sub || !sub->owner) {
+		return 0;
+	}
+	if (!d) {
+		ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
 		return 0;
+	}
 
 	/* Channel is on hold, so we will unhold */
 	if (skinnydebug)
@@ -4471,6 +4497,11 @@ static int handle_transfer_button(struct skinny_subchannel *sub)
 	l = sub->parent;
 	d = l->device;
 
+	if (!d) {
+		ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
+		return -1;
+	}
+
 	if (!sub->related) {
 		/* Another sub has not been created so this must be first XFER press */
 		if (!sub->onhold) {
@@ -4603,6 +4634,11 @@ static int handle_callforward_button(struct skinny_subchannel *sub, int cfwdtype
 	struct ast_channel *c = sub->owner;
 	pthread_t t;
 
+	if (!d) {
+		ast_log(LOG_WARNING, "Device for line %s is not registered.\n", l->name);
+		return 0;
+	}
+
 	if (l->hookstate == SKINNY_ONHOOK) {
 		l->hookstate = SKINNY_OFFHOOK;
 		transmit_speaker_mode(d, SKINNY_SPEAKERON);
-- 
1.7.10