Skip to contentSkip to conversation

sctp: socket.c validate sprstat_policy

PATCH In review Tomas Bortoli 2 participants 3 messages Oct 27, 2018 – Oct 28, 2018

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 sctp: socket.c validate sprstat_policy

It is possible to perform out-of-bound reads on sctp_getsockopt_pr_streamstatus() and on sctp_getsockopt_pr_assocstatus() by passing from userspace a sprstat_policy that overflows the abandoned_sent/abandoned_unsent fixed length arrays. The over-read data are directly copied/leaked to userspace.

---
 net/sctp/socket.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
net/sctp/socket.c +6 -2
index fc0386e8ff23..14dce5d95817 100644
@@ -7083,7 +7083,9 @@ static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
 	}
 
 	policy = params.sprstat_policy;
-	if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
+	if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
+	    __SCTP_PR_INDEX(policy) > SCTP_PR_INDEX(MAX) ||
+	    __SCTP_PR_INDEX(policy) < 0)
 		goto out;
 
 	asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);
@@ -7142,7 +7144,9 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
 	}
 
 	policy = params.sprstat_policy;
-	if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
+	if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
+	    __SCTP_PR_INDEX(policy) > SCTP_PR_INDEX(MAX) ||
+	    __SCTP_PR_INDEX(policy) < 0)
 		goto out;
 
 	asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);
Signature · 1 line
2.11.0
maintainer
#1 lore raw
Quoted 30 lines · Tomas Bortoli

It is possible to perform out-of-bound reads on sctp_getsockopt_pr_streamstatus() and on sctp_getsockopt_pr_assocstatus() by passing from userspace a sprstat_policy that overflows the abandoned_sent/abandoned_unsent fixed length arrays. The over-read data are directly copied/leaked to userspace.

---
 net/sctp/socket.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
net/sctp/socket.c +3 -1
index fc0386e8ff23..14dce5d95817 100644
@@ -7083,7 +7083,9 @@ static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
        }
 
        policy = params.sprstat_policy;
-       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
+       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
+           __SCTP_PR_INDEX(policy) > SCTP_PR_INDEX(MAX) ||
+           __SCTP_PR_INDEX(policy) < 0)
                goto out;
 
        asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);

net/sctp/socket.c static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len, · line 7150

Quoted 8 lines
net/sctp/socket.c +3 -1
@@ -7142,7 +7144,9 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
        }
 
        policy = params.sprstat_policy;
-       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
+       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
+           __SCTP_PR_INDEX(policy) > SCTP_PR_INDEX(MAX) ||
+           __SCTP_PR_INDEX(policy) < 0)
                goto out;

This is not the correct fix.
See https://lkml.org/lkml/2018/10/27/136

#2 lore raw
Quoted 33 lines · Xin Long
Quoted 32 lines · Tomas Bortoli

It is possible to perform out-of-bound reads on sctp_getsockopt_pr_streamstatus() and on sctp_getsockopt_pr_assocstatus() by passing from userspace a sprstat_policy that overflows the abandoned_sent/abandoned_unsent fixed length arrays. The over-read data are directly copied/leaked to userspace.

---
 net/sctp/socket.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)
net/sctp/socket.c +3 -1
index fc0386e8ff23..14dce5d95817 100644
@@ -7083,7 +7083,9 @@ static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len,
        }
 
        policy = params.sprstat_policy;
-       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
+       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
+           __SCTP_PR_INDEX(policy) > SCTP_PR_INDEX(MAX) ||
+           __SCTP_PR_INDEX(policy) < 0)
                goto out;
 
        asoc = sctp_id2assoc(sk, params.sprstat_assoc_id);
@@ -7142,7 +7144,9 @@ static int sctp_getsockopt_pr_streamstatus(struct sock *sk, int len,
        }
 
Quoted 9 lines

net/sctp/socket.c static int sctp_getsockopt_pr_assocstatus(struct sock *sk, int len, · line 7089

Quoted 6 lines
net/sctp/socket.c +3 -1
        policy = params.sprstat_policy;
-       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)))
+       if (!policy || (policy & ~(SCTP_PR_SCTP_MASK | SCTP_PR_SCTP_ALL)) ||
+           __SCTP_PR_INDEX(policy) > SCTP_PR_INDEX(MAX) ||
+           __SCTP_PR_INDEX(policy) < 0)
                goto out;

This is not the correct fix.
See https://lkml.org/lkml/2018/10/27/136

Ack, good to know ty!