• R/O
  • HTTP
  • SSH
  • HTTPS

linux-2.4.36: コミット

2.4.36-stable kernel tree


コミットメタ情報

リビジョンe11056494e595ad9c13d04ac4db0eadd7a59b5e9 (tree)
日時2006-08-27 20:26:37
作者Sridhar Samudrala <sri@us.i...>
コミッターWilly Tarreau

ログメッセージ

[PATCH] [SCTP] Local privilege elevation - CVE-2006-3745

Avoid the use of buggy get_user_iov_size(). sctp_make_abort_user()
now takes the msg_len along with the msg so that we don't have to
recalculate the bytes in iovec. It also uses memcpy_fromiovec()
so that we don't go beyond the length of the allocated buffer.

Signed-off-by: Sridhar Samudrala <sri@us.ibm.com>

変更サマリ

差分

--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -410,19 +410,6 @@ static inline int sctp_list_single_entry(struct list_head *head)
410410 return ((head->next != head) && (head->next == head->prev));
411411 }
412412
413-/* Calculate the size (in bytes) occupied by the data of an iovec. */
414-static inline size_t get_user_iov_size(struct iovec *iov, int iovlen)
415-{
416- size_t retval = 0;
417-
418- for (; iovlen > 0; --iovlen) {
419- retval += iov->iov_len;
420- iov++;
421- }
422-
423- return retval;
424-}
425-
426413 /* Generate a random jitter in the range of -50% ~ +50% of input RTO. */
427414 static inline __s32 sctp_jitter(__u32 rto)
428415 {
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -221,8 +221,7 @@ struct sctp_chunk *sctp_make_abort_no_data(const struct sctp_association *,
221221 const struct sctp_chunk *,
222222 __u32 tsn);
223223 struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *,
224- const struct sctp_chunk *,
225- const struct msghdr *);
224+ const struct msghdr *, size_t msg_len);
226225 struct sctp_chunk *sctp_make_abort_violation(const struct sctp_association *,
227226 const struct sctp_chunk *,
228227 const __u8 *,
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -798,38 +798,26 @@ no_mem:
798798
799799 /* Helper to create ABORT with a SCTP_ERROR_USER_ABORT error. */
800800 struct sctp_chunk *sctp_make_abort_user(const struct sctp_association *asoc,
801- const struct sctp_chunk *chunk,
802- const struct msghdr *msg)
801+ const struct msghdr *msg,
802+ size_t paylen)
803803 {
804804 struct sctp_chunk *retval;
805- void *payload = NULL, *payoff;
806- size_t paylen = 0;
807- struct iovec *iov = NULL;
808- int iovlen = 0;
809-
810- if (msg) {
811- iov = msg->msg_iov;
812- iovlen = msg->msg_iovlen;
813- paylen = get_user_iov_size(iov, iovlen);
814- }
805+ void *payload = NULL;
806+ int err;
815807
816- retval = sctp_make_abort(asoc, chunk, sizeof(sctp_errhdr_t) + paylen);
808+ retval = sctp_make_abort(asoc, NULL, sizeof(sctp_errhdr_t) + paylen);
817809 if (!retval)
818810 goto err_chunk;
819811
820812 if (paylen) {
821813 /* Put the msg_iov together into payload. */
822- payload = kmalloc(paylen, GFP_ATOMIC);
814+ payload = kmalloc(paylen, GFP_KERNEL);
823815 if (!payload)
824816 goto err_payload;
825- payoff = payload;
826817
827- for (; iovlen > 0; --iovlen) {
828- if (copy_from_user(payoff, iov->iov_base,iov->iov_len))
829- goto err_copy;
830- payoff += iov->iov_len;
831- iov++;
832- }
818+ err = memcpy_fromiovec(payload, msg->msg_iov, paylen);
819+ if (err < 0)
820+ goto err_copy;
833821 }
834822
835823 sctp_init_cause(retval, SCTP_ERROR_USER_ABORT, payload, paylen);
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -3990,18 +3990,12 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort(
39903990 * from its upper layer, but retransmits data to the far end
39913991 * if necessary to fill gaps.
39923992 */
3993- struct msghdr *msg = arg;
3994- struct sctp_chunk *abort;
3993+ struct sctp_chunk *abort = arg;
39953994 sctp_disposition_t retval;
39963995
39973996 retval = SCTP_DISPOSITION_CONSUME;
39983997
3999- /* Generate ABORT chunk to send the peer. */
4000- abort = sctp_make_abort_user(asoc, NULL, msg);
4001- if (!abort)
4002- retval = SCTP_DISPOSITION_NOMEM;
4003- else
4004- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
3998+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
40053999
40064000 /* Even if we can't send the ABORT due to low memory delete the
40074001 * TCB. This is a departure from our typical NOMEM handling.
@@ -4123,8 +4117,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
41234117 void *arg,
41244118 sctp_cmd_seq_t *commands)
41254119 {
4126- struct msghdr *msg = arg;
4127- struct sctp_chunk *abort;
4120+ struct sctp_chunk *abort = arg;
41284121 sctp_disposition_t retval;
41294122
41304123 /* Stop T1-init timer */
@@ -4132,12 +4125,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort(
41324125 SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT));
41334126 retval = SCTP_DISPOSITION_CONSUME;
41344127
4135- /* Generate ABORT chunk to send the peer */
4136- abort = sctp_make_abort_user(asoc, NULL, msg);
4137- if (!abort)
4138- retval = SCTP_DISPOSITION_NOMEM;
4139- else
4140- sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
4128+ sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort));
41414129
41424130 sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
41434131 SCTP_STATE(SCTP_STATE_CLOSED));
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -1199,8 +1199,16 @@ SCTP_STATIC int sctp_sendmsg(struct sock *sk, struct msghdr *msg, int msg_len)
11991199 goto out_unlock;
12001200 }
12011201 if (sinfo_flags & MSG_ABORT) {
1202+ struct sctp_chunk *chunk;
1203+
1204+ chunk = sctp_make_abort_user(asoc, msg, msg_len);
1205+ if (!chunk) {
1206+ err = -ENOMEM;
1207+ goto out_unlock;
1208+ }
1209+
12021210 SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc);
1203- sctp_primitive_ABORT(asoc, msg);
1211+ sctp_primitive_ABORT(asoc, chunk);
12041212 err = 0;
12051213 goto out_unlock;
12061214 }
旧リポジトリブラウザで表示