From: Manfred Spraul <manfred@colorfullife.com>
To: "Serge E. Hallyn" <serue@us.ibm.com>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>,
Pavel Emelyanov <xemul@openvz.org>,
Linux Kernel Mailing List <linux-kernel@vger.kernel.org>,
Andrew Morton <akpm@linux-foundation.org>,
Sukadev Bhattiprolu <sukadev@us.ibm.com>
Subject: Re: [RFC, PATCH] fix SEM_UNDO with namespaces
Date: Sun, 06 Apr 2008 17:11:32 +0200 [thread overview]
Message-ID: <47F8E824.6090600@colorfullife.com> (raw)
In-Reply-To: <20080404043902.GA14177@sergelap.austin.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 1408 bytes --]
Serge E. Hallyn wrote:
>> diff --git a/ipc/namespace.c b/ipc/namespace.c
>> index 9171d94..9044505 100644
>> --- a/ipc/namespace.c
>> +++ b/ipc/namespace.c
>> @@ -48,6 +48,16 @@ struct ipc_namespace *copy_ipcs(unsigned long flags, struct ipc_namespace *ns)
>> if (!(flags & CLONE_NEWIPC))
>> return ns;
>>
>> + if (!(flags & CLONE_SYSVSEM)) {
>>
>
> Wait, this should be opposite, right?
>
> [snip]
> Manfred, I'm trying to test this, but can't get an error without this
> patch. Do you have a testcase?
The patch is bogus, sorry that I didn't notice it immediately.
The problem is ipc/sem.c, function find_undo, lookup_undo:
lookup_undo doesn't check the namespace pointer, thus a simple single
threaded app can trigger the problem.
Attached is a test app and a kernel patch that shows the problem.
Run the test app immediately after boot (or within a new ipc namespace),
otherwise the ipc sequence counter will prevent the app from triggering
the problem: The undo structure that was created before unshare() [i.e.
with 1 semaphore in it] will be used after unshare() [i.e. semaphore 100
will be accessed].
With kernel debugging (full slub debugging) enabled, I even got an oops
when I tried to ipcrm the left over array after running undons, probably
because the undo structure was freed at exit_sem() within the new
namespace, but still used in the outer namespace.
--
Manfred
[-- Attachment #2: undons.c --]
[-- Type: text/plain, Size: 3350 bytes --]
/*
* 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 <sched.h>
#include <wait.h>
#define CLONE_NEWIPC 0x08000000 /* New ipcs */
#endif
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <assert.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>
#include <pthread.h>
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;
}
[-- Attachment #3: patch-help --]
[-- Type: text/plain, Size: 636 bytes --]
diff --git a/ipc/sem.c b/ipc/sem.c
index 0b45a4d..5c882f9 100644
--- a/ipc/sem.c
+++ b/ipc/sem.c
@@ -1081,6 +1082,7 @@ static struct sem_undo *find_undo(struct ipc_namespace *ns, int semid)
new->id_next = sma->undo;
sma->undo = new;
sem_unlock(sma);
+printk(KERN_ERR "find_undo(%p, %x) new undop %p (for %d sems).\n", ns, semid, new, nsems);
un = new;
spin_unlock(&ulp->lock);
out:
@@ -1153,6 +1155,7 @@ retry_undos:
error = PTR_ERR(sma);
goto out_free;
}
+printk(KERN_ERR "find_undo(%p, %x) == %p, using %ld sems.\n", ns, semid, un, sma->sem_nsems);
/*
* semid identifiers are not unique - find_undo may have
next prev parent reply other threads:[~2008-04-06 15:11 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2008-03-30 20:50 [RFC, PATCH] fix SEM_UNDO with namespaces Manfred Spraul
2008-03-31 7:12 ` Pavel Emelyanov
2008-03-31 16:14 ` Manfred Spraul
2008-04-01 9:44 ` Pavel Emelyanov
2008-04-01 14:15 ` Serge E. Hallyn
2008-04-03 19:04 ` Andrew Morton
2008-04-03 19:31 ` Manfred Spraul
2008-04-01 15:25 ` Eric W. Biederman
2008-04-03 19:40 ` Manfred Spraul
2008-04-03 19:44 ` Serge E. Hallyn
2008-04-04 4:39 ` Serge E. Hallyn
2008-04-06 15:11 ` Manfred Spraul [this message]
2008-04-06 16:26 ` [PATCH] fix SEM_UNDO with namespaces, take 2 Manfred Spraul
2008-04-07 7:21 ` Pavel Emelyanov
2008-04-07 17:03 ` Manfred Spraul
2008-04-08 8:09 ` Pavel Emelyanov
2008-04-14 21:10 ` [RFC, PATCH] fix SEM_UNDO with namespaces Serge E. Hallyn
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=47F8E824.6090600@colorfullife.com \
--to=manfred@colorfullife.com \
--cc=akpm@linux-foundation.org \
--cc=ebiederm@xmission.com \
--cc=linux-kernel@vger.kernel.org \
--cc=serue@us.ibm.com \
--cc=sukadev@us.ibm.com \
--cc=xemul@openvz.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox