/* * Copyright (C) 1999,2001 by Manfred Spraul. * * Redistribution of this file is permitted under the terms of the GNU * General Public License (GPL) * $Header: /home/manfred/cvs-tree/manfred/ipcsem/undotest.c,v 1.2 2003/06/28 15:19:43 manfred Exp $ */ #ifdef __LINUX__ #define _GNU_SOURCE #include #include #define CLONE_NEWIPC 0x08000000 /* New ipcs */ #endif #include #include #include #include #include #include #include #include #include #include #include #include union semun { int val; struct semid_ds *buf; unsigned short int *array; struct seminfo* __buf; }; int getval(char * str, int id) { union semun arg; int res; res = semctl(id,0,GETVAL,arg); if(res==-1) { printf("GETVAL failed for %s.\n", str); exit(4); } printf(" %s: GETVAL now %d.\n",str, res); return res; } void setzero(int id) { union semun arg; int res; arg.val = 0; res = semctl(id,0,SETVAL,arg); if(res==-1) { printf("SETVAL failed, errno %d.\n", errno); exit(4); } printf(" SETVAL succeeded.\n"); } /* test1: verify that undo works at all. */ int main(int argc,char** argv) { int res, id; printf(" ****************************************\n"); /* create array */ res = semget(IPC_PRIVATE, 1, 0700 | IPC_CREAT); printf(" got semaphore array %xh.\n",res); if(res == -1) { printf(" create failed.\n"); return 1; } id = res; setzero(id); res = getval("test1 init", id); if (res != 0) { printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); printf("Bad: got unexpected value.\n"); exit(99); } /* create sub-process */ res = fork(); if (res < 0) { printf("Fork failed (errno=%d). Aborting.\n", errno); res = semctl(id,1,IPC_RMID,NULL); exit(1); } fflush(stdout); if (!res) { struct sembuf sop[1]; int id2; sop[0].sem_num=0; sop[0].sem_op=1; sop[0].sem_flg=SEM_UNDO; res = semop(id,sop,1); if(res==-1) { printf("semop failed.\n"); exit(1); } res = getval("before unshare()", id); if (res != 1) { printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); printf("Bad: got unexpected value.\n"); exit(99); } fflush(stdout); errno = 0; res = unshare(CLONE_NEWNS|CLONE_NEWIPC); printf(" unshare returned %d, errno now %d (expected: 0,0).\n", res, errno); fflush(stdout); /* create array */ res = semget(IPC_PRIVATE, 101, 0700 | IPC_CREAT); printf(" got semaphore array %xh.\n",res); if(res == -1) { printf(" create failed.\n"); return 1; } id2 = res; printf("Now operating on id1=%x, id2=%x. (if both are equal, there will be a memory corruption)\n", id, id2); /* child: */ sop[0].sem_num=100; sop[0].sem_op=1; sop[0].sem_flg=SEM_UNDO; // This operation should trash kernel memory (if id1==id2) res = semop(id2,sop,1); if(res==-1) { printf("semop failed.\n"); exit(1); } exit(1); } else { int retval; retval = wait4(res, NULL, 0, NULL); if (retval != res) { printf("wait4 returned unexpeted value %d, errno now %d.\n", retval, errno); } res = getval("after exit", id); if (res != 0) { printf("XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX\n"); printf("Bad: got unexpected value.\n"); return 1; } } return 0; }