[PATCH 2/5] __FD_ELT: Implement correct buffer overflow check
KOSAKI Motohiro
kosaki.motohiro@gmail.com
Sun Apr 14 00:47:00 GMT 2013
Signed-off-by: KOSAKI Motohiro <kosaki.motohiro@gmail.com>
---
ChangeLog | 14 ++++++++++++++
bits/select.h | 6 +++---
debug/Versions | 3 +++
debug/fdelt_chk.c | 11 +++++++++++
misc/bits/select2.h | 23 +++++++++++++----------
misc/sys/select.h | 2 +-
sysdeps/x86/bits/select.h | 6 +++---
7 files changed, 48 insertions(+), 17 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 5311919..36bac6a 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2013-04-13 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
+
+ * misc/sys/select.h (__FD_ELT): Add fdset new argument.
+ * bits/select.h (__FD_SET, __FD_CLR, __FD_ISSET): Adapt
+ an above change.
+ * sysdeps/x86/bits/select.h (__FD_SET, __FD_CLR, __FD_ISSET):
+ Likewise.
+
+ * debug/fdelt_chk.c (__fdelt_buffer_chk): New.
+ * misc/bits/select2.h (__FD_ELT): Implement correct buffer
+ overflow check instead of hardcoded FD_SET_SIZE.
+
+ * debug/Versions: Added __fdelt_buffer_chk and __fdelt_buffer_warn.
+
2013-03-25 KOSAKI Motohiro <kosaki.motohiro@gmail.com>
* debug/fdelt_chk.c (__fdelt_chk): Removed range check
diff --git a/bits/select.h b/bits/select.h
index ca87676..a10e18a 100644
--- a/bits/select.h
+++ b/bits/select.h
@@ -30,8 +30,8 @@
__FDS_BITS (__arr)[__i] = 0; \
} while (0)
#define __FD_SET(d, s) \
- ((void) (__FDS_BITS (s)[__FD_ELT(d)] |= __FD_MASK(d)))
+ ((void) (__FDS_BITS (s)[__FD_ELT(d, s)] |= __FD_MASK(d)))
#define __FD_CLR(d, s) \
- ((void) (__FDS_BITS (s)[__FD_ELT(d)] &= ~__FD_MASK(d)))
+ ((void) (__FDS_BITS (s)[__FD_ELT(d, s)] &= ~__FD_MASK(d)))
#define __FD_ISSET(d, s) \
- ((__FDS_BITS (s)[__FD_ELT (d)] & __FD_MASK (d)) != 0)
+ ((__FDS_BITS (s)[__FD_ELT (d, s)] & __FD_MASK (d)) != 0)
diff --git a/debug/Versions b/debug/Versions
index c1722fa..1ef2994 100644
--- a/debug/Versions
+++ b/debug/Versions
@@ -55,6 +55,9 @@ libc {
GLIBC_2.16 {
__poll_chk; __ppoll_chk;
}
+ GLIBC_2.18 {
+ __fdelt_buffer_chk; __fdelt_buffer_warn;
+ }
GLIBC_PRIVATE {
__fortify_fail;
}
diff --git a/debug/fdelt_chk.c b/debug/fdelt_chk.c
index 6588be0..8e16dc5 100644
--- a/debug/fdelt_chk.c
+++ b/debug/fdelt_chk.c
@@ -15,6 +15,7 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <sys/types.h>
#include <sys/select.h>
@@ -25,3 +26,13 @@ __fdelt_nochk (long int d)
}
strong_alias (__fdelt_nochk, __fdelt_chk)
strong_alias (__fdelt_nochk, __fdelt_warn)
+
+long int
+__fdelt_buffer_chk (long int fd, size_t buflen)
+{
+ if (fd / 8 >= buflen)
+ __chk_fail ();
+
+ return fd / __NFDBITS;;
+}
+strong_alias (__fdelt_buffer_chk, __fdelt_buffer_warn)
diff --git a/misc/bits/select2.h b/misc/bits/select2.h
index 03558c9..a0ffbb7 100644
--- a/misc/bits/select2.h
+++ b/misc/bits/select2.h
@@ -21,15 +21,18 @@
#endif
/* Helper functions to issue warnings and errors when needed. */
-extern long int __fdelt_chk (long int __d);
-extern long int __fdelt_warn (long int __d)
+extern long int __fdelt_buffer_chk (long int __d, size_t buflen);
+extern long int __fdelt_buffer_warn (long int __d, size_t buflen)
__warnattr ("bit outside of fd_set selected");
+
#undef __FD_ELT
-#define __FD_ELT(d) \
- __extension__ \
- ({ long int __d = (d); \
- (__builtin_constant_p (__d) \
- ? (0 <= __d && __d < __FD_SETSIZE \
- ? (__d / __NFDBITS) \
- : __fdelt_warn (__d)) \
- : __fdelt_chk (__d)); })
+#define __FD_ELT(d, s) \
+ __extension__ \
+ ({ \
+ long int __d = (d); \
+ (__bos0 (s) != (size_t) -1) \
+ ? (__builtin_constant_p (__d) && ((__d / 8) >= __bos0 (s))) \
+ ? __fdelt_buffer_warn(__d, __bos0 (s)) \
+ : __fdelt_buffer_chk(__d, __bos0 (s)) \
+ : __d / __NFDBITS; \
+ })
diff --git a/misc/sys/select.h b/misc/sys/select.h
index 21351fe..341190c 100644
--- a/misc/sys/select.h
+++ b/misc/sys/select.h
@@ -57,7 +57,7 @@ typedef long int __fd_mask;
#undef __NFDBITS
/* It's easier to assume 8-bit bytes than to get CHAR_BIT. */
#define __NFDBITS (8 * (int) sizeof (__fd_mask))
-#define __FD_ELT(d) ((d) / __NFDBITS)
+#define __FD_ELT(d, s) ((d) / __NFDBITS)
#define __FD_MASK(d) ((__fd_mask) 1 << ((d) % __NFDBITS))
/* fd_set for select and pselect. */
diff --git a/sysdeps/x86/bits/select.h b/sysdeps/x86/bits/select.h
index 8b87188..b29f301 100644
--- a/sysdeps/x86/bits/select.h
+++ b/sysdeps/x86/bits/select.h
@@ -56,8 +56,8 @@
#endif /* GNU CC */
#define __FD_SET(d, set) \
- ((void) (__FDS_BITS (set)[__FD_ELT (d)] |= __FD_MASK (d)))
+ ((void) (__FDS_BITS (set)[__FD_ELT (d, set)] |= __FD_MASK (d)))
#define __FD_CLR(d, set) \
- ((void) (__FDS_BITS (set)[__FD_ELT (d)] &= ~__FD_MASK (d)))
+ ((void) (__FDS_BITS (set)[__FD_ELT (d, set)] &= ~__FD_MASK (d)))
#define __FD_ISSET(d, set) \
- ((__FDS_BITS (set)[__FD_ELT (d)] & __FD_MASK (d)) != 0)
+ ((__FDS_BITS (set)[__FD_ELT (d, set)] & __FD_MASK (d)) != 0)
--
1.7.1
More information about the Libc-ports
mailing list