From d25c879dc55dcc6a477fdce1c75382afec7596b8 Mon Sep 17 00:00:00 2001 From: Greg McGary Date: Thu, 27 Jul 2000 06:25:28 +0000 Subject: [PATCH] * sysdeps/gnu/bits/msq.h: Qualify kernel's data structure pointers as __unbounded. * sysdeps/unix/sysv/linux/mips/bits/shm.h: Likewise. * sysdeps/generic/bp-semctl.h: New file. * sysdeps/unix/sysv/linux/msgctl.c: Qualify kernel's data structure pointers as __unbounded. Check bounds of syscall args. * sysdeps/unix/sysv/linux/msgrcv.c: Likewise. * sysdeps/unix/sysv/linux/msgsnd.c: Likewise. * sysdeps/unix/sysv/linux/semctl.c: Likewise. * sysdeps/unix/sysv/linux/semop.c: Likewise. * sysdeps/unix/sysv/linux/shmat.c: Likewise. * sysdeps/unix/sysv/linux/shmctl.c: Likewise. * sysdeps/unix/sysv/linux/shmdt.c: Likewise. * sysdeps/unix/sysv/linux/alpha/msgctl.c: Likewise. * sysdeps/unix/sysv/linux/alpha/semctl.c: Likewise. * sysdeps/unix/sysv/linux/alpha/shmctl.c: Likewise. * sysdeps/unix/sysv/linux/i386/msgctl.c: Likewise. * sysdeps/unix/sysv/linux/i386/semctl.c: Likewise. * sysdeps/unix/sysv/linux/i386/shmctl.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c: Likewise. 2000-07-26 Greg McGary * sysdeps/gnu/bits/msq.h: Qualify kernel's data structure pointers as __unbounded. * sysdeps/unix/sysv/linux/mips/bits/shm.h: Likewise. * sysdeps/generic/bp-semctl.h: New file. * sysdeps/unix/sysv/linux/msgctl.c: Qualify kernel's data structure pointers as __unbounded. Check bounds of syscall args. * sysdeps/unix/sysv/linux/msgrcv.c: Likewise. * sysdeps/unix/sysv/linux/msgsnd.c: Likewise. * sysdeps/unix/sysv/linux/semctl.c: Likewise. * sysdeps/unix/sysv/linux/semop.c: Likewise. * sysdeps/unix/sysv/linux/shmat.c: Likewise. * sysdeps/unix/sysv/linux/shmctl.c: Likewise. * sysdeps/unix/sysv/linux/shmdt.c: Likewise. * sysdeps/unix/sysv/linux/alpha/msgctl.c: Likewise. * sysdeps/unix/sysv/linux/alpha/semctl.c: Likewise. * sysdeps/unix/sysv/linux/alpha/shmctl.c: Likewise. * sysdeps/unix/sysv/linux/i386/msgctl.c: Likewise. * sysdeps/unix/sysv/linux/i386/semctl.c: Likewise. * sysdeps/unix/sysv/linux/i386/shmctl.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c: Likewise. * sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c: Likewise. --- ChangeLog | 25 ++++++++++ sysdeps/generic/bp-semctl.h | 69 ++++++++++++++++++++++++++ sysdeps/gnu/bits/msq.h | 8 +-- sysdeps/unix/sysv/linux/alpha/msgctl.c | 18 +++---- sysdeps/unix/sysv/linux/alpha/semctl.c | 15 ++++-- sysdeps/unix/sysv/linux/alpha/shmctl.c | 13 ++--- sysdeps/unix/sysv/linux/i386/msgctl.c | 24 +++++---- sysdeps/unix/sysv/linux/i386/semctl.c | 18 +++++-- sysdeps/unix/sysv/linux/i386/shmctl.c | 21 +++++--- sysdeps/unix/sysv/linux/mips/bits/shm.h | 6 +-- sysdeps/unix/sysv/linux/msgctl.c | 23 +++++---- sysdeps/unix/sysv/linux/msgrcv.c | 7 +-- sysdeps/unix/sysv/linux/msgsnd.c | 5 +- sysdeps/unix/sysv/linux/semctl.c | 30 +++++++---- sysdeps/unix/sysv/linux/semop.c | 4 +- sysdeps/unix/sysv/linux/shmat.c | 27 +++++++--- sysdeps/unix/sysv/linux/shmctl.c | 16 +++--- sysdeps/unix/sysv/linux/shmdt.c | 2 +- sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c | 3 +- sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c | 5 +- sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c | 3 +- 21 files changed, 251 insertions(+), 91 deletions(-) create mode 100644 sysdeps/generic/bp-semctl.h diff --git a/ChangeLog b/ChangeLog index 0edb792..b6075c6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,28 @@ +2000-07-26 Greg McGary + + * sysdeps/gnu/bits/msq.h: Qualify kernel's + data structure pointers as __unbounded. + * sysdeps/unix/sysv/linux/mips/bits/shm.h: Likewise. + * sysdeps/generic/bp-semctl.h: New file. + * sysdeps/unix/sysv/linux/msgctl.c: Qualify kernel's data structure + pointers as __unbounded. Check bounds of syscall args. + * sysdeps/unix/sysv/linux/msgrcv.c: Likewise. + * sysdeps/unix/sysv/linux/msgsnd.c: Likewise. + * sysdeps/unix/sysv/linux/semctl.c: Likewise. + * sysdeps/unix/sysv/linux/semop.c: Likewise. + * sysdeps/unix/sysv/linux/shmat.c: Likewise. + * sysdeps/unix/sysv/linux/shmctl.c: Likewise. + * sysdeps/unix/sysv/linux/shmdt.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/msgctl.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/semctl.c: Likewise. + * sysdeps/unix/sysv/linux/alpha/shmctl.c: Likewise. + * sysdeps/unix/sysv/linux/i386/msgctl.c: Likewise. + * sysdeps/unix/sysv/linux/i386/semctl.c: Likewise. + * sysdeps/unix/sysv/linux/i386/shmctl.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c: Likewise. + * sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c: Likewise. + 2000-07-26 Ulrich Drepper * libio/iofwide.c: Enable transliteration for conversion from wchar_t diff --git a/sysdeps/generic/bp-semctl.h b/sysdeps/generic/bp-semctl.h new file mode 100644 index 0000000..86a6b27 --- /dev/null +++ b/sysdeps/generic/bp-semctl.h @@ -0,0 +1,69 @@ +/* Bounded-pointer checking macros for C. + Copyright (C) 2000 Free Software Foundation, Inc. + Contributed by Greg McGary + + This file is part of the GNU C Library. Its master source is NOT part of + the C library, however. The master source lives in the GNU MP Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with the GNU C Library; see the file COPYING.LIB. If not, + write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +#ifndef _bp_semctl_h_ +#define _bp_semctl_h_ 1 + +#if __BOUNDED_POINTERS__ + +# define CHECK_SEMCTL(ARGP, SEMID, CMD) check_semctl (ARGP, SEMID, CMD) + +union semun *__unbounded +check_semctl (union semun *arg, int semid, int cmd) +{ + int ipc64 = (cmd & __IPC_64); + + switch (cmd & ~__IPC_64) + { + case IPC_STAT: + case IPC_SET: + (void) CHECK_1 (arg->buf); + break; + + case GETALL: + case SETALL: + { + struct semid_ds ds; + union semun un = { buf: &ds; }; + unsigned int length = ~0; + + /* It's unfortunate that we need to make a recursive + system call to get the size of the semaphore set... */ + if (semctl (semid, semnum, IPC_STAT | ipc64, un) == 0) + length = ds.sem_nsems; + (void) CHECK_N (arg->array, length); + break; + } + + case IPC_INFO: + (void) CHECK_1 (arg->__buf); + break; + } + + return __ptrvalue (arg); +} + +#else +# define CHECK_SEMCTL(ARGP, SEMID, CMD) (ARGP) +#endif + +#endif /* _bp_semctl_h_ */ diff --git a/sysdeps/gnu/bits/msq.h b/sysdeps/gnu/bits/msq.h index 874c369..55032eb 100644 --- a/sysdeps/gnu/bits/msq.h +++ b/sysdeps/gnu/bits/msq.h @@ -38,13 +38,13 @@ typedef unsigned short int msglen_t; struct msqid_ds { struct ipc_perm msg_perm; /* structure describing operation permission */ - struct msg *__msg_first; /* pointer to first message on queue */ - struct msg *__msg_last; /* pointer to last message on queue */ + struct msg *__unbounded __msg_first; /* pointer to first message on queue */ + struct msg *__unbounded __msg_last; /* pointer to last message on queue */ __time_t msg_stime; /* time of last msgsnd command */ __time_t msg_rtime; /* time of last msgrcv command */ __time_t msg_ctime; /* time of last change */ - struct wait_queue *__wwait; /* ??? */ - struct wait_queue *__rwait; /* ??? */ + struct wait_queue *__unbounded __wwait; /* ??? */ + struct wait_queue *__unbounded __rwait; /* ??? */ unsigned short int __msg_cbytes;/* current number of bytes on queue */ msgqnum_t msg_qnum; /* number of messages currently on queue */ msglen_t msg_qbytes; /* max number of bytes allowed on queue */ diff --git a/sysdeps/unix/sysv/linux/alpha/msgctl.c b/sysdeps/unix/sysv/linux/alpha/msgctl.c index 709b5c0..c568299 100644 --- a/sysdeps/unix/sysv/linux/alpha/msgctl.c +++ b/sysdeps/unix/sysv/linux/alpha/msgctl.c @@ -24,19 +24,20 @@ #include #include #include +#include #include "kernel-features.h" struct __old_msqid_ds { struct __old_ipc_perm msg_perm; /* structure describing operation permission */ - struct msg *__msg_first; /* pointer to first message on queue */ - struct msg *__msg_last; /* pointer to last message on queue */ + struct msg *__unbounded __msg_first; /* pointer to first message on queue */ + struct msg *__unbounded __msg_last; /* pointer to last message on queue */ __time_t msg_stime; /* time of last msgsnd command */ __time_t msg_rtime; /* time of last msgrcv command */ __time_t msg_ctime; /* time of last change */ - struct wait_queue *__wwait; /* ??? */ - struct wait_queue *__rwait; /* ??? */ + struct wait_queue *__unbounded __wwait; /* ??? */ + struct wait_queue *__unbounded __rwait; /* ??? */ unsigned short int __msg_cbytes; /* current number of bytes on queue */ unsigned short int msg_qnum; /* number of messages currently on queue */ unsigned short int msg_qbytes; /* max number of bytes allowed on queue */ @@ -57,7 +58,7 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) of time. However, msg_qnum and msg_qbytes changed size at the same time the size of uid changed elsewhere. */ #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (msgctl, 3, msqid, cmd | __IPC_64, buf); + return INLINE_SYSCALL (msgctl, 3, msqid, cmd | __IPC_64, CHECK_1 (buf)); #else switch (cmd) { case MSG_STAT: @@ -65,7 +66,7 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) case IPC_SET: break; default: - return INLINE_SYSCALL (msgctl, 3, msqid, cmd, buf); + return INLINE_SYSCALL (msgctl, 3, msqid, cmd, CHECK_1 (buf)); } { @@ -74,7 +75,7 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) /* Unfortunately there is no way how to find out for sure whether we should use old or new msgctl. */ - result = INLINE_SYSCALL (msgctl, 3, msqid, cmd | __IPC_64, buf); + result = INLINE_SYSCALL (msgctl, 3, msqid, cmd | __IPC_64, CHECK_1 (buf)); if (result != -1 || errno != EINVAL) return result; @@ -93,7 +94,7 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) return -1; } } - result = INLINE_SYSCALL (msgctl, 3, msqid, cmd, &old); + result = INLINE_SYSCALL (msgctl, 3, msqid, cmd, __ptrvalue (&old)); if (result != -1 && cmd != IPC_SET) { memset(buf, 0, sizeof(*buf)); @@ -120,4 +121,3 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) #include versioned_symbol (libc, __new_msgctl, msgctl, GLIBC_2_2); - diff --git a/sysdeps/unix/sysv/linux/alpha/semctl.c b/sysdeps/unix/sysv/linux/alpha/semctl.c index 4be4fb2..48bc2d4 100644 --- a/sysdeps/unix/sysv/linux/alpha/semctl.c +++ b/sysdeps/unix/sysv/linux/alpha/semctl.c @@ -49,6 +49,9 @@ union semun struct seminfo *__buf; /* buffer for IPC_INFO */ }; +#include +#include /* definition of CHECK_SEMCTL needs union semum */ + extern int __syscall_semctl (int, int, int, void *); /* Return identifier for array of NSEMS semaphores associated with @@ -69,7 +72,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) va_end (ap); #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (semctl, 4, semid, semnum, cmd | __IPC_64, &arg); + return INLINE_SYSCALL (semctl, 4, semid, semnum, cmd | __IPC_64, + CHECK_SEMCTL (&arg, semid, cmd | __IPC_64)); #else switch (cmd) { case SEM_STAT: @@ -77,7 +81,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) case IPC_SET: break; default: - return INLINE_SYSCALL (semctl, 4, semid, semnum, cmd, &arg); + return INLINE_SYSCALL (semctl, 4, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); } { @@ -87,7 +92,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) /* Unfortunately there is no way how to find out for sure whether we should use old or new semctl. */ - result = INLINE_SYSCALL (semctl, 4, semid, semnum, cmd | __IPC_64, &arg); + result = INLINE_SYSCALL (semctl, 4, semid, semnum, cmd | __IPC_64, + CHECK_SEMCTL (&arg, semid, cmd | __IPC_64)); if (result != -1 || errno != EINVAL) return result; @@ -106,7 +112,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) return -1; } } - result = INLINE_SYSCALL (semctl, 4, semid, semnum, cmd, &arg); + result = INLINE_SYSCALL (semctl, 4, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); if (result != -1 && cmd != IPC_SET) { memset(buf, 0, sizeof(*buf)); diff --git a/sysdeps/unix/sysv/linux/alpha/shmctl.c b/sysdeps/unix/sysv/linux/alpha/shmctl.c index 70c420d..bd5b881 100644 --- a/sysdeps/unix/sysv/linux/alpha/shmctl.c +++ b/sysdeps/unix/sysv/linux/alpha/shmctl.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "kernel-features.h" @@ -39,8 +40,8 @@ struct __old_shmid_ds __ipc_pid_t shm_lpid; /* pid of last shmop */ unsigned short int shm_nattch; /* number of current attaches */ unsigned short int __shm_npages; /* size of segment (pages) */ - unsigned long int *__shm_pages; /* array of ptrs to frames -> SHMMAX */ - struct vm_area_struct *__attaches; /* descriptors for attaches */ + unsigned long int *__unbounded __shm_pages; /* array of ptrs to frames -> SHMMAX */ + struct vm_area_struct *__unbounded __attaches; /* descriptors for attaches */ }; struct __old_shminfo @@ -61,7 +62,7 @@ int __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) { #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, buf); + return INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, CHECK_1 (buf)); #else switch (cmd) { case SHM_STAT: @@ -70,7 +71,7 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) case IPC_INFO: break; default: - return INLINE_SYSCALL (shmctl, 3, shmid, cmd, buf); + return INLINE_SYSCALL (shmctl, 3, shmid, cmd, CHECK_1 (buf)); } { @@ -79,7 +80,7 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) /* Unfortunately there is no way how to find out for sure whether we should use old or new shmctl. */ - result = INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, buf); + result = INLINE_SYSCALL (shmctl, 3, shmid, cmd | __IPC_64, CHECK_1 (buf)); if (result != -1 || errno != EINVAL) return result; @@ -96,7 +97,7 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) return -1; } } - result = INLINE_SYSCALL (shmctl, 3, shmid, cmd, &old); + result = INLINE_SYSCALL (shmctl, 3, shmid, cmd, __ptrvalue (&old)); if (result != -1 && (cmd == SHM_STAT || cmd == IPC_STAT)) { memset(buf, 0, sizeof(*buf)); diff --git a/sysdeps/unix/sysv/linux/i386/msgctl.c b/sysdeps/unix/sysv/linux/i386/msgctl.c index 684365a..f7535ae 100644 --- a/sysdeps/unix/sysv/linux/i386/msgctl.c +++ b/sysdeps/unix/sysv/linux/i386/msgctl.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "kernel-features.h" #include @@ -31,13 +32,13 @@ struct __old_msqid_ds { struct __old_ipc_perm msg_perm; /* structure describing operation permission */ - struct msg *__msg_first; /* pointer to first message on queue */ - struct msg *__msg_last; /* pointer to last message on queue */ + struct msg *__unbounded __msg_first; /* pointer to first message on queue */ + struct msg *__unbounded __msg_last; /* pointer to last message on queue */ __time_t msg_stime; /* time of last msgsnd command */ __time_t msg_rtime; /* time of last msgrcv command */ __time_t msg_ctime; /* time of last change */ - struct wait_queue *__wwait; /* ??? */ - struct wait_queue *__rwait; /* ??? */ + struct wait_queue *__unbounded __wwait; /* ??? */ + struct wait_queue *__unbounded __rwait; /* ??? */ unsigned short int __msg_cbytes; /* current number of bytes on queue */ unsigned short int msg_qnum; /* number of messages currently on queue */ unsigned short int msg_qbytes; /* max number of bytes allowed on queue */ @@ -64,7 +65,8 @@ extern int __libc_missing_32bit_uids; int __old_msgctl (int msqid, int cmd, struct __old_msqid_ds *buf) { - return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd, 0, CHECK_1 (buf)); } compat_symbol (libc, __old_msgctl, msgctl, GLIBC_2_0); #endif @@ -73,7 +75,8 @@ int __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) { #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd | __IPC_64, 0, CHECK_1 (buf)); #else switch (cmd) { case MSG_STAT: @@ -81,7 +84,8 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) case IPC_SET: break; default: - return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd, 0, CHECK_1 (buf)); } { @@ -105,7 +109,8 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) } if (__libc_missing_32bit_uids <= 0) { - result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf); + result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd | __IPC_64, 0, CHECK_1 (buf)); return result; } } @@ -124,7 +129,8 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) return -1; } } - result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, &old); + result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd, 0, __ptrvalue (&old)); if (result != -1 && cmd != IPC_SET) { memset(buf, 0, sizeof(*buf)); diff --git a/sysdeps/unix/sysv/linux/i386/semctl.c b/sysdeps/unix/sysv/linux/i386/semctl.c index b553c2a..6fdd83c 100644 --- a/sysdeps/unix/sysv/linux/i386/semctl.c +++ b/sysdeps/unix/sysv/linux/i386/semctl.c @@ -50,6 +50,9 @@ union semun struct seminfo *__buf; /* buffer for IPC_INFO */ }; +#include +#include /* definition of CHECK_SEMCTL needs union semum */ + #ifdef __NR_getuid32 # if __ASSUME_32BITUIDS == 0 /* This variable is shared with all files that need to check for 32bit @@ -79,7 +82,8 @@ __old_semctl (int semid, int semnum, int cmd, ...) va_end (ap); - return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg); + return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); } compat_symbol (libc, __old_semctl, semctl, GLIBC_2_0); #endif @@ -98,7 +102,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) va_end (ap); #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, &arg); + return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, + CHECK_SEMCTL (&arg, semid, cmd | __IPC_64)); #else switch (cmd) { case SEM_STAT: @@ -106,7 +111,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) case IPC_SET: break; default: - return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg); + return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); } { @@ -131,7 +137,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) } if (__libc_missing_32bit_uids <= 0) { - result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, &arg); + result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, + CHECK_SEMCTL (&arg, semid, cmd | __IPC_64)); return result; } } @@ -151,7 +158,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) return -1; } } - result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg); + result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); if (result != -1 && cmd != IPC_SET) { memset(buf, 0, sizeof(*buf)); diff --git a/sysdeps/unix/sysv/linux/i386/shmctl.c b/sysdeps/unix/sysv/linux/i386/shmctl.c index ca25ff0..402fb46 100644 --- a/sysdeps/unix/sysv/linux/i386/shmctl.c +++ b/sysdeps/unix/sysv/linux/i386/shmctl.c @@ -25,6 +25,7 @@ #include #include #include +#include #include "kernel-features.h" #include @@ -40,8 +41,8 @@ struct __old_shmid_ds __ipc_pid_t shm_lpid; /* pid of last shmop */ unsigned short int shm_nattch; /* number of current attaches */ unsigned short int __shm_npages; /* size of segment (pages) */ - unsigned long int *__shm_pages; /* array of ptrs to frames -> SHMMAX */ - struct vm_area_struct *__attaches; /* descriptors for attaches */ + unsigned long int *__unbounded __shm_pages; /* array of ptrs to frames -> SHMMAX */ + struct vm_area_struct *__unbounded __attaches; /* descriptors for attaches */ }; struct __old_shminfo @@ -71,7 +72,8 @@ int __new_shmctl (int, int, struct shmid_ds *); int __old_shmctl (int shmid, int cmd, struct __old_shmid_ds *buf) { - return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, + shmid, cmd, 0, CHECK_1 (buf)); } compat_symbol (libc, __old_shmctl, shmctl, GLIBC_2_0); #endif @@ -80,7 +82,8 @@ int __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) { #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, + shmid, cmd | __IPC_64, 0, CHECK_1 (buf)); #else switch (cmd) { case SHM_STAT: @@ -91,7 +94,8 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) # endif break; default: - return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, + shmid, cmd, 0, CHECK_1 (buf)); } { @@ -114,8 +118,8 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) __set_errno(save_errno); } if (__libc_missing_32bit_uids <= 0) - return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, - 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, + shmid, cmd | __IPC_64, 0, CHECK_1 (buf)); } # endif @@ -131,7 +135,8 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) return -1; } } - result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, &old); + result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, + shmid, cmd, 0, __ptrvalue (&old)); if (result != -1 && (cmd == SHM_STAT || cmd == IPC_STAT)) { memset(buf, 0, sizeof(*buf)); diff --git a/sysdeps/unix/sysv/linux/mips/bits/shm.h b/sysdeps/unix/sysv/linux/mips/bits/shm.h index 20e75e0..31c65a9 100644 --- a/sysdeps/unix/sysv/linux/mips/bits/shm.h +++ b/sysdeps/unix/sysv/linux/mips/bits/shm.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc. +/* Copyright (C) 1995, 1996, 1997, 2000 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or @@ -48,8 +48,8 @@ struct shmid_ds long int shm_lpid; /* pid of last shmop */ unsigned short int shm_nattch; /* number of current attaches */ unsigned short int __shm_npages; /* size of segment (pages) */ - unsigned long int *__shm_pages; /* array of ptrs to frames -> SHMMAX */ - struct vm_area_struct *__attaches; /* descriptors for attaches */ + unsigned long int *__unbounded __shm_pages; /* array of ptrs to frames -> SHMMAX */ + struct vm_area_struct *__unbounded __attaches; /* descriptors for attaches */ }; #ifdef __USE_MISC diff --git a/sysdeps/unix/sysv/linux/msgctl.c b/sysdeps/unix/sysv/linux/msgctl.c index 2b2b411..fb0ad56 100644 --- a/sysdeps/unix/sysv/linux/msgctl.c +++ b/sysdeps/unix/sysv/linux/msgctl.c @@ -25,19 +25,20 @@ #include #include #include +#include #include "kernel-features.h" struct __old_msqid_ds { struct __old_ipc_perm msg_perm; /* structure describing operation permission */ - struct msg *__msg_first; /* pointer to first message on queue */ - struct msg *__msg_last; /* pointer to last message on queue */ + struct msg *__unbounded __msg_first; /* pointer to first message on queue */ + struct msg *__unbounded __msg_last; /* pointer to last message on queue */ __time_t msg_stime; /* time of last msgsnd command */ __time_t msg_rtime; /* time of last msgrcv command */ __time_t msg_ctime; /* time of last change */ - struct wait_queue *__wwait; /* ??? */ - struct wait_queue *__rwait; /* ??? */ + struct wait_queue *__unbounded __wwait; /* ??? */ + struct wait_queue *__unbounded __rwait; /* ??? */ unsigned short int __msg_cbytes; /* current number of bytes on queue */ unsigned short int msg_qnum; /* number of messages currently on queue */ unsigned short int msg_qbytes; /* max number of bytes allowed on queue */ @@ -56,7 +57,7 @@ int __new_msgctl (int, int, struct msqid_ds *); int __old_msgctl (int msqid, int cmd, struct __old_msqid_ds *buf) { - return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, CHECK_1 (buf)); } compat_symbol (libc, __old_msgctl, msgctl, GLIBC_2_0); #endif @@ -65,7 +66,8 @@ int __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) { #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd | __IPC_64, 0, CHECK_1 (buf)); #else switch (cmd) { case MSG_STAT: @@ -73,7 +75,8 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) case IPC_SET: break; default: - return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd, 0, CHECK_1 (buf)); } { @@ -82,7 +85,8 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) /* Unfortunately there is no way how to find out for sure whether we should use old or new msgctl. */ - result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd | __IPC_64, 0, buf); + result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd | __IPC_64, 0, CHECK_1 (buf)); if (result != -1 || errno != EINVAL) return result; @@ -101,7 +105,8 @@ __new_msgctl (int msqid, int cmd, struct msqid_ds *buf) return -1; } } - result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, &old); + result = INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, + msqid, cmd, 0, __ptrvalue (&old)); if (result != -1 && cmd != IPC_SET) { memset(buf, 0, sizeof(*buf)); diff --git a/sysdeps/unix/sysv/linux/msgrcv.c b/sysdeps/unix/sysv/linux/msgrcv.c index d0da0d6..0971143 100644 --- a/sysdeps/unix/sysv/linux/msgrcv.c +++ b/sysdeps/unix/sysv/linux/msgrcv.c @@ -24,12 +24,13 @@ #include #include +#include /* Kludge to work around Linux' restriction of only up to five arguments to a system call. */ struct ipc_kludge { - void *msgp; + void *__unbounded msgp; long int msgtyp; }; @@ -46,8 +47,8 @@ msgrcv (msqid, msgp, msgsz, msgtyp, msgflg) fives parameters to a system call. */ struct ipc_kludge tmp; - tmp.msgp = msgp; + tmp.msgp = CHECK_N (msgp, msgsz); tmp.msgtyp = msgtyp; - return INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg, &tmp); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgrcv, msqid, msgsz, msgflg, __ptrvalue (&tmp)); } diff --git a/sysdeps/unix/sysv/linux/msgsnd.c b/sysdeps/unix/sysv/linux/msgsnd.c index 43a5a87..a068556 100644 --- a/sysdeps/unix/sysv/linux/msgsnd.c +++ b/sysdeps/unix/sysv/linux/msgsnd.c @@ -24,6 +24,8 @@ #include #include +#include + int msgsnd (msqid, msgp, msgsz, msgflg) int msqid; @@ -31,5 +33,6 @@ msgsnd (msqid, msgp, msgsz, msgflg) size_t msgsz; int msgflg; { - return INLINE_SYSCALL (ipc, 5, IPCOP_msgsnd, msqid, msgsz, msgflg, (void *)msgp); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgsnd, msqid, msgsz, + msgflg, CHECK_N (msgp, msgsz)); } diff --git a/sysdeps/unix/sysv/linux/semctl.c b/sysdeps/unix/sysv/linux/semctl.c index 7ea8ee6..0d64b95 100644 --- a/sysdeps/unix/sysv/linux/semctl.c +++ b/sysdeps/unix/sysv/linux/semctl.c @@ -34,10 +34,10 @@ struct __old_semid_ds struct __old_ipc_perm sem_perm; /* operation permission struct */ __time_t sem_otime; /* last semop() time */ __time_t sem_ctime; /* last time changed by semctl() */ - struct sem *__sembase; /* ptr to first semaphore in array */ - struct sem_queue *__sem_pending; /* pending operations */ - struct sem_queue *__sem_pending_last; /* last pending operation */ - struct sem_undo *__undo; /* ondo requests on this array */ + struct sem *__unbounded __sembase; /* ptr to first semaphore in array */ + struct sem_queue *__unbounded __sem_pending; /* pending operations */ + struct sem_queue *__unbounded __sem_pending_last; /* last pending operation */ + struct sem_undo *__unbounded __undo; /* ondo requests on this array */ unsigned short int sem_nsems; /* number of semaphores in set */ }; @@ -50,6 +50,8 @@ union semun struct seminfo *__buf; /* buffer for IPC_INFO */ }; +#include +#include /* definition of CHECK_SEMCTL needs union semum */ /* Return identifier for array of NSEMS semaphores associated with KEY. */ @@ -72,7 +74,8 @@ __old_semctl (int semid, int semnum, int cmd, ...) va_end (ap); - return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg); + return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); } compat_symbol (libc, __old_semctl, semctl, GLIBC_2_0); #endif @@ -91,16 +94,19 @@ __new_semctl (int semid, int semnum, int cmd, ...) va_end (ap); #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, &arg); + return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, + CHECK_SEMCTL (&arg, semid, cmd | __IPC_64)); #else - switch (cmd) { + switch (cmd) + { case SEM_STAT: case IPC_STAT: case IPC_SET: break; default: - return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg); - } + return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); + } { int save_errno = errno, result; @@ -109,7 +115,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) /* Unfortunately there is no way how to find out for sure whether we should use old or new semctl. */ - result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, &arg); + result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd | __IPC_64, + CHECK_SEMCTL (&arg, semid, cmd | __IPC_64)); if (result != -1 || errno != EINVAL) return result; @@ -128,7 +135,8 @@ __new_semctl (int semid, int semnum, int cmd, ...) return -1; } } - result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg); + result = INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); if (result != -1 && cmd != IPC_SET) { memset(buf, 0, sizeof(*buf)); diff --git a/sysdeps/unix/sysv/linux/semop.c b/sysdeps/unix/sysv/linux/semop.c index a4dd58d..59138a3 100644 --- a/sysdeps/unix/sysv/linux/semop.c +++ b/sysdeps/unix/sysv/linux/semop.c @@ -23,6 +23,7 @@ #include #include +#include /* Perform user-defined atomical operation of array of semaphores. */ @@ -32,5 +33,6 @@ semop (semid, sops, nsops) struct sembuf *sops; size_t nsops; { - return INLINE_SYSCALL (ipc, 5, IPCOP_semop, semid, (int) nsops, 0, sops); + return INLINE_SYSCALL (ipc, 5, IPCOP_semop, + semid, (int) nsops, 0, CHECK_N (sops, nsops)); } diff --git a/sysdeps/unix/sysv/linux/shmat.c b/sysdeps/unix/sysv/linux/shmat.c index e2035c9..33dc016 100644 --- a/sysdeps/unix/sysv/linux/shmat.c +++ b/sysdeps/unix/sysv/linux/shmat.c @@ -23,6 +23,7 @@ #include #include +#include /* Attach the shared memory segment associated with SHMID to the data segment of the calling process. SHMADDR and SHMFLG determine how @@ -34,11 +35,23 @@ shmat (shmid, shmaddr, shmflg) const void *shmaddr; int shmflg; { - long int retval; - unsigned long raddr; - - retval = INLINE_SYSCALL (ipc, 5, IPCOP_shmat, shmid, shmflg, - (long int) &raddr, (void *) shmaddr); - return ((unsigned long int) retval > -(unsigned long int) SHMLBA - ? (void *) retval : (void *) raddr); + void *__unbounded result; + void *__unbounded raddr; + +#if __BOUNDED_POINTERS__ + size_t length = ~0; + struct shmid_ds shmds; + /* It's unfortunate that we need to make another system call to get + the shared memory segment length... */ + if (shmctl (shmid, ICP_STAT, &shmds) == 0) + length = shmds.shm_segsz; +#endif + + result = (void *__unbounded) INLINE_SYSCALL (ipc, 5, IPCOP_shmat, shmid, shmflg, + __ptrvalue (&raddr), + __ptrvalue (shmaddr)); + if ((unsigned long) result <= -(unsigned long) SHMLBA) + result = raddr; + + return BOUNDED_N (result, length); } diff --git a/sysdeps/unix/sysv/linux/shmctl.c b/sysdeps/unix/sysv/linux/shmctl.c index f2f7340..3b2809a 100644 --- a/sysdeps/unix/sysv/linux/shmctl.c +++ b/sysdeps/unix/sysv/linux/shmctl.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "kernel-features.h" @@ -40,8 +41,8 @@ struct __old_shmid_ds __ipc_pid_t shm_lpid; /* pid of last shmop */ unsigned short int shm_nattch; /* number of current attaches */ unsigned short int __shm_npages; /* size of segment (pages) */ - unsigned long int *__shm_pages; /* array of ptrs to frames -> SHMMAX */ - struct vm_area_struct *__attaches; /* descriptors for attaches */ + unsigned long int *__unbounded __shm_pages; /* array of ptrs to frames -> SHMMAX */ + struct vm_area_struct *__unbounded __attaches; /* descriptors for attaches */ }; struct __old_shminfo @@ -63,7 +64,8 @@ int __new_shmctl (int, int, struct shmid_ds *); int __old_shmctl (int shmid, int cmd, struct __old_shmid_ds *buf) { - return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, + cmd, 0, CHECK_1opt (buf)); } compat_symbol (libc, __old_shmctl, shmctl, GLIBC_2_0); #endif @@ -72,7 +74,7 @@ int __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) { #if __ASSUME_32BITUIDS > 0 - return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, CHECK_1 (buf)); #else switch (cmd) { case SHM_STAT: @@ -83,7 +85,7 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) #endif break; default: - return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, CHECK_1 (buf)); } { @@ -92,7 +94,7 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) /* Unfortunately there is no way how to find out for sure whether we should use old or new shmctl. */ - result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, buf); + result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd | __IPC_64, 0, CHECK_1 (buf)); if (result != -1 || errno != EINVAL) return result; @@ -109,7 +111,7 @@ __new_shmctl (int shmid, int cmd, struct shmid_ds *buf) return -1; } } - result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, &old); + result = INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, __ptrvalue (&old)); if (result != -1 && (cmd == SHM_STAT || cmd == IPC_STAT)) { memset(buf, 0, sizeof(*buf)); diff --git a/sysdeps/unix/sysv/linux/shmdt.c b/sysdeps/unix/sysv/linux/shmdt.c index 436ed6e..371e646 100644 --- a/sysdeps/unix/sysv/linux/shmdt.c +++ b/sysdeps/unix/sysv/linux/shmdt.c @@ -31,5 +31,5 @@ int shmdt (shmaddr) const void *shmaddr; { - return INLINE_SYSCALL (ipc, 5, IPCOP_shmdt, 0, 0, 0, (void *) shmaddr); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmdt, 0, 0, 0, __ptrvalue ((void *) shmaddr)); } diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c b/sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c index c537eea..e06edcc 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/msgctl.c @@ -23,6 +23,7 @@ #include #include +#include /* Allows to control internal state and destruction of message queue objects. */ @@ -33,5 +34,5 @@ msgctl (msqid, cmd, buf) int cmd; struct msqid_ds *buf; { - return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_msgctl, msqid, cmd, 0, CHECK_1 (buf)); } diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c b/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c index ab7ad85..7d42cd6 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/semctl.c @@ -34,6 +34,8 @@ union semun struct seminfo *__buf; /* buffer for IPC_INFO */ }; +#include +#include /* definition of CHECK_SEMCTL needs union semum */ /* Return identifier for array of NSEMS semaphores associated with KEY. */ @@ -51,5 +53,6 @@ semctl (int semid, int semnum, int cmd, ...) va_end (ap); - return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, &arg); + return INLINE_SYSCALL (ipc, 5, IPCOP_semctl, semid, semnum, cmd, + CHECK_SEMCTL (&arg, semid, cmd)); } diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c b/sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c index cc9b6a5..a29ccc3 100644 --- a/sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/shmctl.c @@ -23,6 +23,7 @@ #include #include +#include /* Provide operations to control over shared memory segments. */ @@ -32,5 +33,5 @@ shmctl (shmid, cmd, buf) int cmd; struct shmid_ds *buf; { - return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, buf); + return INLINE_SYSCALL (ipc, 5, IPCOP_shmctl, shmid, cmd, 0, CHECK_1 (buf)); } -- 2.7.4