n-i-bz fix bug in strspn replacement
n-i-bz Add support for the Linux BLKFLSBUF ioctl
n-i-bz Add support for the Linux BLKREPORTZONE and BLKRESETZONE ioctls
+n-i-bz Fix possible stack trashing by semctl syscall wrapping
Release 3.13.0 (15 June 2017)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static
UInt get_sem_count( Int semid )
{
- struct vki_semid_ds buf;
union vki_semun arg;
SysRes res;
- /* Doesn't actually seem to be necessary, but gcc-4.4.0 20081017
- (experimental) otherwise complains that the use in the return
- statement below is uninitialised. */
- buf.sem_nsems = 0;
-
- arg.buf = &buf;
-
# if defined(__NR_semctl)
+ struct vki_semid64_ds buf;
+ arg.buf64 = &buf;
res = VG_(do_syscall4)(__NR_semctl, semid, 0, VKI_IPC_STAT, *(UWord *)&arg);
+ if (sr_isError(res))
+ return 0;
+
+ return buf.sem_nsems;
# elif defined(__NR_semsys) /* Solaris */
+ struct vki_semid_ds buf;
+ arg.buf = &buf;
res = VG_(do_syscall5)(__NR_semsys, VKI_SEMCTL, semid, 0, VKI_IPC_STAT,
*(UWord *)&arg);
+ if (sr_isError(res))
+ return 0;
+
+ return buf.sem_nsems;
# else
+ struct vki_semid_ds buf;
+ arg.buf = &buf;
res = VG_(do_syscall5)(__NR_ipc, 3 /* IPCOP_semctl */, semid, 0,
VKI_IPC_STAT, (UWord)&arg);
-# endif
if (sr_isError(res))
return 0;
return buf.sem_nsems;
+# endif
}
void
union vki_semun {
int val; /* value for SETVAL */
struct vki_semid_ds __user *buf; /* buffer for IPC_STAT & IPC_SET */
+ struct vki_semid64_ds __user *buf64; /* buffer for IPC_STAT & IPC_SET */
unsigned short __user *array; /* array for GETALL & SETALL */
struct vki_seminfo __user *__buf; /* buffer for IPC_INFO */
void __user *__pad;
#include <sys/sem.h>
#include <time.h>
#include <unistd.h>
+
+void semctl_test (int trace, const char *fname)
+{
+ key_t key;
+ int semid;
+ int nr_of_readers;
+ int ret;
+
+ union semun {
+ int val; /* Value for SETVAL */
+ struct semid_ds *buf; /* Buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* Array for GETALL, SETALL */
+ struct seminfo *__buf; /* Buffer for IPC_INFO
+ (Linux-specific) */
+ } u;
+
+ struct semid_ds ds;
+
+ key = ftok (fname, 1);
+ if (key == -1)
+ perror ("ftok");
+ nr_of_readers = 4;
+
+ semid = semget (key, 2 * nr_of_readers, IPC_CREAT + 0660);
+ if (semid == -1) {
+ perror ("semget");
+ }
+ if (trace)
+ printf("semid %d\n", semid);
+
+ u.buf = &ds;
+ ret = semctl (semid, 0, IPC_STAT, u);
+ if (ret == -1)
+ perror("semctl IPC_STAT");
+ if (trace)
+ printf("semid %d sem_nsems %d\n", semid, (int) ds.sem_nsems);
+
+ {
+ unsigned short semarray[2 * nr_of_readers];
+ for (int count = 0; count < nr_of_readers; count++) {
+ semarray[2 * count] = 0;
+ semarray[2 * count + 1] = 1000;
+ }
+ ret = semctl (semid, 0, SETALL, semarray);
+ if (ret == -1)
+ perror ("semctl SETALL");
+ }
+
+ ret = semctl (semid, 0, IPC_RMID);
+ if (ret == -1)
+ perror ("semctl IPC_RMID");
+}
+
int main(int argc, char **argv)
{
int semid;
perror("semctl(IPC_RMID)");
exit(1);
}
-
+
+ semctl_test(argc > 1, argv[0]);
exit(0);
}