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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.