Bug 10423
Summary: | (Patch queued)af_rose sendmsg length check | ||
---|---|---|---|
Product: | Networking | Reporter: | tp (thomas.pollet) |
Component: | Other | Assignee: | Arnaldo Carvalho de Melo (acme) |
Status: | RESOLVED CODE_FIX | ||
Severity: | normal | CC: | alan, eugeneteo, ralf |
Priority: | P1 | ||
Hardware: | All | ||
OS: | Linux | ||
Kernel Version: | 2.6.24.4 | Subsystem: | |
Regression: | No | Bisected commit-id: |
Description
tp
2008-04-08 06:48:26 UTC
Reply-To: akpm@linux-foundation.org (switched to email. Please respond via emailed reply-to-all, not via the bugzilla web interface). On Tue, 8 Apr 2008 06:48:27 -0700 (PDT) bugme-daemon@bugzilla.kernel.org wrote: > http://bugzilla.kernel.org/show_bug.cgi?id=10423 > > Summary: af_rose sendmsg length check > Product: Networking > Version: 2.5 > KernelVersion: 2.6.24.4 > Platform: All > OS/Version: Linux > Tree: Mainline > Status: NEW > Severity: normal > Priority: P1 > Component: Other > AssignedTo: acme@ghostprotocols.net > ReportedBy: thomas.pollet@gmail.com > > > Hi, > > the code from rose_sendmsg in sys/net/af_rose.c doesn't check the value of > len. > suppose len is very big (0xfffffff8 for example) then "size" would overflow. > > size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + > ROSE_MIN_LEN; > > resulting in a buffer that's too small. > > if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, > &err)) > == NULL) > return err; > > the buffer is filled here: > > 1115 skb_put(skb, len); > 1116 > 1117 err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, > len); > > It might be that it doesn't need to check. We check that the total length didn't overflow negative in sys_sendmsg()'s call to verify_iovec(). Of course, the addition which you identify might make a very large length overflow 0x7fffffff, and subsequent code might handle that incorrectly. (In reply to comment #0) > the code from rose_sendmsg in sys/net/af_rose.c doesn't check the value of > len. > suppose len is very big (0xfffffff8 for example) then "size" would overflow. > > size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + > ROSE_MIN_LEN; > > resulting in a buffer that's too small. I believe that if sock_alloc_send_skb() is called with a wrapped size, it might actually create a larger buffer than necessary. 1883 asmlinkage long sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags) 1884 { [...] 1895 int err, ctl_len, iov_size, total_len; [...] 1930 err = verify_iovec(&msg_sys, iov, 1931 (struct sockaddr *)&address, 1932 VERIFY_READ); 1933 if (err < 0) 1934 goto out_freeiov; 1935 total_len = err; ^ total_len is not negative [...] 1971 err = sock_sendmsg(sock, &msg_sys, total_len); ^ total_len casted to size_t 567 int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) 568 { [...] 575 ret = __sock_sendmsg(&iocb, sock, msg, size); 549 static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, 550 struct msghdr *msg, size_t size) 551 { [...] 558 si->size = size; ^ size_t to positive signed int [...] 564 return sock->ops->sendmsg(iocb, sock, msg, size); 1063 static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, 1064 struct msghdr *msg, size_t len) 1065 { [...] 1073 int n, size, qbit = 0; [...] 1123 size = len + AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN; ^ the summation is converted into a signed int 1124 1125 if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) ^ converted to unsigned long ^ size could wrap, and become a huge value. it will in turn, ^ truncate to an unsigned int when it is called with alloc_skb 1126 return err; 1127 1128 skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN); [...] 1136 skb_put(skb, len); ^ unsigned int 1137 1138 err = memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len); ^ len is signed int; only copy if len is more than > 0 1139 if (err) { 1140 kfree_skb(skb); 1141 return err; 1142 } |