lkml.org 
[lkml]   [1999]   [Jun]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectDynamic MSGMAX patch for 2.2.9

This is nothing but Peeter Joot's old kernel patch; I'm posting an
updated version because the latest public code of his was a patch
against 2.1.131 that didn't apply cleanly to 2.2.9. This is the
result of editing code by hand in accordance with the patch, testing
the new compiled kernel, and "diff -ur"ing the changes. Email me if
I've screwed something up.

The patch's effect is to provide dynamic, larger values (runtime
configurable via /proc) for MSGMAX, MSGMNB (and MSGPOOL). It uses a
dynamic kmalloc'ed buffer for data in SysV messages that won't fit on
one 4k page.

I suspect this is too late for inclusion into later 2.2 kernels (even
if it is a short, clean change) - but can we please see a large
default MSGMAX in an official Linux kernel soon? I'm porting SysV
software from HP-UX at the moment (surprisingly easy, aside from this
problem) and an inability to send 16k messages is fatal in more than
one program.
---
Roy Stogner
Sandia National Laboratories, Org. 5715
rhstogn@sandia.gov
---
Patch appended:
------cut-here------
diff -ur linux/Documentation/sysctl/kernel.txt linux-new/Documentation/sysctl/kernel.txt
--- linux/Documentation/sysctl/kernel.txt Mon Apr 12 11:10:27 1999
+++ linux-new/Documentation/sysctl/kernel.txt Mon Jun 7 15:56:03 1999
@@ -26,6 +26,9 @@
- java-interpreter [ binfmt_java, obsolete ]
- l2cr [ PPC only ]
- modprobe ==> Documentation/kmod.txt
+- msgmax [ sysv ipc ]
+- msgmnb [ sysv ipc ]
+- msgpool [ sysv ipc ]
- osrelease
- ostype
- panic
@@ -114,6 +117,38 @@
this is the fifth kernel built from this source base and the
date behind it indicates the time the kernel was built.
The only way to tune these values is to rebuild the kernel :-)
+
+==============================================================
+
+msgmax:
+
+This value can be used to query and set the run time limit
+on the maximum message size that can be sent. This defaults
+to MSGMAX, which despite it's small size (4056) seems to have
+been sufficient for a long time.
+
+msgmax is now effectively limited by physical memory. Users
+should note that indiscriminately increasing this limit is not
+a good idea since queued messages are stored in non swappable
+kernel space. Increasing this limit should be accompanied
+with suitable modifications to msgmnb and msgpool.
+
+==============================================================
+
+msgmnb:
+
+This value can be used to query and set the default maximum
+number of bytes in a message queue. Note that this can also
+be set on a per queue basis via msgctl, but a root user is
+required to do so. This value defaults to MSGMNB.
+
+==============================================================
+
+msgpool:
+
+This value can be used to query and set the maximum total
+number of bytes in all message queues. This value defaults
+to MSGPOOL*1024.

==============================================================

diff -ur linux/include/linux/msg.h linux-new/include/linux/msg.h
--- linux/include/linux/msg.h Sun Dec 27 23:19:28 1998
+++ linux-new/include/linux/msg.h Mon Jun 7 16:00:13 1999
@@ -12,18 +12,38 @@
#define MSG_EXCEPT 020000 /* recv any msg except of specified type.*/

/* one msqid structure for each queue on the system */
-struct msqid_ds {
+struct msqid_ds_base {
struct ipc_perm msg_perm;
struct msg *msg_first; /* first message on queue */
struct msg *msg_last; /* last message in queue */
__kernel_time_t msg_stime; /* last msgsnd time */
__kernel_time_t msg_rtime; /* last msgrcv time */
__kernel_time_t msg_ctime; /* last change time */
+};
+
+#ifdef __KERNEL__
+
+struct msqid_ds_kernel {
+ struct msqid_ds_base u;
struct wait_queue *wwait;
struct wait_queue *rwait;
- unsigned short msg_cbytes; /* current number of bytes on queue */
+ unsigned int msg_cbytes; /* current number of bytes on queue */
unsigned short msg_qnum; /* number of messages in queue */
- unsigned short msg_qbytes; /* max number of bytes on queue */
+ unsigned int msg_qbytes; /* max number of bytes on queue */
+ __kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
+ __kernel_ipc_pid_t msg_lrpid; /* last receive pid */
+};
+
+#endif
+
+struct msqid_ds {
+ struct msqid_ds_base u;
+ /* unions used to maintain size on 64 bit platforms */
+ union { void * __wwait ; unsigned int msg_cbytes; } c;
+ union { void * __rwait ; unsigned int msg_qbytes; } q;
+ unsigned short old_msg_cbytes; /* current number of bytes on queue */
+ unsigned short msg_qnum; /* number of messages in queue */
+ unsigned short old_msg_qbytes; /* max number of bytes on queue */
__kernel_ipc_pid_t msg_lspid; /* pid of last msgsnd */
__kernel_ipc_pid_t msg_lrpid; /* last receive pid */
};
@@ -47,12 +67,15 @@
};

#define MSGMNI 128 /* <= 1K */ /* max # of msg queue identifiers */
+
+/* Default values, now configurable at run time */
#define MSGMAX 4056 /* <= 4056 */ /* max size of message (bytes) */
-#define MSGMNB 16384 /* ? */ /* default max size of a message queue */
+#define MSGMNB 16384 /* default max size of a message queue */
+#define __MSGPOOL (MSGMNI*MSGMNB) /* size of message pool */
+#define MSGPOOL (__MSGPOOL/1024) /* size in kilobytes of message pool */

/* unused */
-#define MSGPOOL (MSGMNI*MSGMNB/1024) /* size in kilobytes of message pool */
-#define MSGTQL MSGMNB /* number of system message headers */
+#define MSGTQL (MSGMNB*MSGMNI) /* number of system message headers */
#define MSGMAP MSGMNB /* number of entries in message map */
#define MSGSSZ 16 /* message segment size */
#define __MSGSEG ((MSGPOOL*1024)/ MSGSSZ) /* max no. of segments */
@@ -66,7 +89,7 @@
long msg_type;
char *msg_spot; /* message text address */
time_t msg_stime; /* msgsnd time */
- short msg_ts; /* message text size */
+ int msg_ts; /* message text size */
};

asmlinkage int sys_msgget (key_t key, int msgflg);
diff -ur linux/ipc/msg.c linux-new/ipc/msg.c
--- linux/ipc/msg.c Fri Nov 20 12:43:19 1998
+++ linux-new/ipc/msg.c Mon Jun 7 16:10:26 1999
@@ -2,11 +2,12 @@
* linux/ipc/msg.c
* Copyright (C) 1992 Krishna Balasubramanian
*
+ * Removed 4056 bytes MSGMAX restriction and 64K restrictions, made dynamic
* Removed all the remaining kerneld mess
* Catch the -EFAULT stuff properly
* Use GFP_KERNEL for messages as in 1.2
* Fixed up the unchecked user space derefs
- * Copyright (C) 1998 Alan Cox & Andi Kleen
+ * Copyright (C) 1998 Alan Cox, Andi Kleen & Peeter Joot
*
*/

@@ -15,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/smp_lock.h>
#include <linux/init.h>
+#include <linux/vmalloc.h>

#include <asm/uaccess.h>

@@ -24,7 +26,7 @@
static int newque (key_t key, int msgflg);
static int findkey (key_t key);

-static struct msqid_ds *msgque[MSGMNI];
+static struct msqid_ds_kernel *msgque[MSGMNI];
static int msgbytes = 0;
static int msghdrs = 0;
static unsigned short msg_seq = 0;
@@ -32,12 +34,16 @@
static int max_msqid = 0;
static struct wait_queue *msg_lock = NULL;

+int msgmax = MSGMAX;
+int msgmnb = MSGMNB;
+int msgpool = __MSGPOOL;
+
void __init msg_init (void)
{
int id;

for (id = 0; id < MSGMNI; id++)
- msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+ msgque[id] = (struct msqid_ds_kernel *) IPC_UNUSED;
msgbytes = msghdrs = msg_seq = max_msqid = used_queues = 0;
msg_lock = NULL;
return;
@@ -45,13 +51,13 @@

static int real_msgsnd (int msqid, struct msgbuf *msgp, size_t msgsz, int msgflg)
{
- int id;
- struct msqid_ds *msq;
+ int id, error;
+ struct msqid_ds_kernel *msq;
struct ipc_perm *ipcp;
struct msg *msgh;
long mtype;

- if (msgsz > MSGMAX || (long) msgsz < 0 || msqid < 0)
+ if (msgsz > msgmax || (long) msgsz < 0 || msqid < 0)
return -EINVAL;
if (get_user(mtype, &msgp->mtype))
return -EFAULT;
@@ -61,43 +67,53 @@
msq = msgque [id];
if (msq == IPC_UNUSED || msq == IPC_NOID)
return -EINVAL;
- ipcp = &msq->msg_perm;
+ ipcp = &msq->u.msg_perm;

slept:
- if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI)
+ if (msq->u.msg_perm.seq != (unsigned int) msqid / MSGMNI)
return -EIDRM;

if (ipcperms(ipcp, S_IWUGO))
return -EACCES;

+ /* There were two identical if statements here? */
if (msgsz + msq->msg_cbytes > msq->msg_qbytes) {
- if (msgsz + msq->msg_cbytes > msq->msg_qbytes) {
- /* still no space in queue */
- if (msgflg & IPC_NOWAIT)
- return -EAGAIN;
- if (signal_pending(current))
- return -EINTR;
- interruptible_sleep_on (&msq->wwait);
- goto slept;
- }
+ /* still no space in queue */
+ if (msgflg & IPC_NOWAIT)
+ return -EAGAIN;
+ if (signal_pending(current))
+ return -EINTR;
+ interruptible_sleep_on (&msq->wwait);
+ goto slept;
}
-
+
/* allocate message header and text space*/
- msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz, GFP_KERNEL);
- if (!msgh)
- return -ENOMEM;
- msgh->msg_spot = (char *) (msgh + 1);
+ if (msgsz < MSGMAX) {
+ /* Standard small message: */
+ msgh = (struct msg *) kmalloc (sizeof(*msgh) + msgsz,
+ GFP_KERNEL);
+ if (!msgh)
+ return -ENOMEM;
+ msgh->msg_spot = (char *) (msgh + 1);
+ } else {
+ msgh = (struct msg *) kmalloc (sizeof(*msgh), GFP_KERNEL);
+ if (!msgh)
+ return -ENOMEM;
+ msgh->msg_spot = (char *) vmalloc(msgsz);
+ if (!msgh->msg_spot)
+ kfree(msgh);
+ }

if (copy_from_user(msgh->msg_spot, msgp->mtext, msgsz))
{
- kfree(msgh);
- return -EFAULT;
+ error = -EFAULT;
+ goto free_buf;
}

if (msgque[id] == IPC_UNUSED || msgque[id] == IPC_NOID
- || msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
- kfree(msgh);
- return -EIDRM;
+ || msq->u.msg_perm.seq != (unsigned int) msqid / MSGMNI) {
+ error = -EIDRM;
+ goto free_buf;
}

msgh->msg_next = NULL;
@@ -105,25 +121,31 @@
msgh->msg_type = mtype;
msgh->msg_stime = CURRENT_TIME;

- if (!msq->msg_first)
- msq->msg_first = msq->msg_last = msgh;
+ if (!msq->u.msg_first)
+ msq->u.msg_first = msq->u.msg_last = msgh;
else {
- msq->msg_last->msg_next = msgh;
- msq->msg_last = msgh;
+ msq->u.msg_last->msg_next = msgh;
+ msq->u.msg_last = msgh;
}
msq->msg_cbytes += msgsz;
- msgbytes += msgsz;
+ msgbytes += msgsz;
msghdrs++;
msq->msg_qnum++;
msq->msg_lspid = current->pid;
- msq->msg_stime = CURRENT_TIME;
+ msq->u.msg_stime = CURRENT_TIME;
wake_up (&msq->rwait);
return 0;
+
+free_buf:
+ if (msgsz >= MSGMAX)
+ vfree(msgh->msg_spot);
+ kfree(msgh);
+ return error;
}

static int real_msgrcv (int msqid, struct msgbuf *msgp, size_t msgsz, long msgtyp, int msgflg)
{
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;
struct ipc_perm *ipcp;
struct msg *tmsg, *leastp = NULL;
struct msg *nmsg = NULL;
@@ -136,7 +158,7 @@
msq = msgque [id];
if (msq == IPC_NOID || msq == IPC_UNUSED)
return -EINVAL;
- ipcp = &msq->msg_perm;
+ ipcp = &msq->u.msg_perm;

/*
* find message of correct type.
@@ -145,7 +167,7 @@
* msgtyp < 0 => get message with least type must be < abs(msgtype).
*/
while (!nmsg) {
- if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI) {
+ if (msq->u.msg_perm.seq != (unsigned int) msqid / MSGMNI) {
return -EIDRM;
}
if (ipcperms (ipcp, S_IRUGO)) {
@@ -153,23 +175,23 @@
}

if (msgtyp == 0)
- nmsg = msq->msg_first;
+ nmsg = msq->u.msg_first;
else if (msgtyp > 0) {
if (msgflg & MSG_EXCEPT) {
- for (tmsg = msq->msg_first; tmsg;
+ for (tmsg = msq->u.msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_type != msgtyp)
break;
nmsg = tmsg;
} else {
- for (tmsg = msq->msg_first; tmsg;
+ for (tmsg = msq->u.msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_type == msgtyp)
break;
nmsg = tmsg;
}
} else {
- for (leastp = tmsg = msq->msg_first; tmsg;
+ for (leastp = tmsg = msq->u.msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_type < leastp->msg_type)
leastp = tmsg;
@@ -182,21 +204,21 @@
return -E2BIG;
}
msgsz = (msgsz > nmsg->msg_ts)? nmsg->msg_ts : msgsz;
- if (nmsg == msq->msg_first)
- msq->msg_first = nmsg->msg_next;
+ if (nmsg == msq->u.msg_first)
+ msq->u.msg_first = nmsg->msg_next;
else {
- for (tmsg = msq->msg_first; tmsg;
+ for (tmsg = msq->u.msg_first; tmsg;
tmsg = tmsg->msg_next)
if (tmsg->msg_next == nmsg)
break;
tmsg->msg_next = nmsg->msg_next;
- if (nmsg == msq->msg_last)
- msq->msg_last = tmsg;
+ if (nmsg == msq->u.msg_last)
+ msq->u.msg_last = tmsg;
}
if (!(--msq->msg_qnum))
- msq->msg_last = msq->msg_first = NULL;
+ msq->u.msg_last = msq->u.msg_first = NULL;

- msq->msg_rtime = CURRENT_TIME;
+ msq->u.msg_rtime = CURRENT_TIME;
msq->msg_lrpid = current->pid;
msgbytes -= nmsg->msg_ts;
msghdrs--;
@@ -205,6 +227,8 @@
if (put_user (nmsg->msg_type, &msgp->mtype) ||
copy_to_user (msgp->mtext, nmsg->msg_spot, msgsz))
msgsz = -EFAULT;
+ if (nmsg->msg_ts >= MSGMAX)
+ vfree(nmsg->msg_spot);
kfree(nmsg);
return msgsz;
} else { /* did not find a message */
@@ -244,14 +268,14 @@
static int findkey (key_t key)
{
int id;
- struct msqid_ds *msq;
+struct msqid_ds_kernel *msq;

for (id = 0; id <= max_msqid; id++) {
while ((msq = msgque[id]) == IPC_NOID)
interruptible_sleep_on (&msg_lock);
if (msq == IPC_UNUSED)
continue;
- if (key == msq->msg_perm.key)
+ if (key == msq->u.msg_perm.key)
return id;
}
return -1;
@@ -260,48 +284,48 @@
static int newque (key_t key, int msgflg)
{
int id;
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;
struct ipc_perm *ipcp;

for (id = 0; id < MSGMNI; id++)
if (msgque[id] == IPC_UNUSED) {
- msgque[id] = (struct msqid_ds *) IPC_NOID;
+ msgque[id] = (struct msqid_ds_kernel *) IPC_NOID;
goto found;
}
return -ENOSPC;

found:
- msq = (struct msqid_ds *) kmalloc (sizeof (*msq), GFP_KERNEL);
+ msq = (struct msqid_ds_kernel *) kmalloc (sizeof (*msq), GFP_KERNEL);
if (!msq) {
- msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+ msgque[id] = (struct msqid_ds_kernel *) IPC_UNUSED;
wake_up (&msg_lock);
return -ENOMEM;
}
- ipcp = &msq->msg_perm;
+ ipcp = &msq->u.msg_perm;
ipcp->mode = (msgflg & S_IRWXUGO);
ipcp->key = key;
ipcp->cuid = ipcp->uid = current->euid;
ipcp->gid = ipcp->cgid = current->egid;
- msq->msg_perm.seq = msg_seq;
- msq->msg_first = msq->msg_last = NULL;
+ msq->u.msg_perm.seq = msg_seq;
+ msq->u.msg_first = msq->u.msg_last = NULL;
msq->rwait = msq->wwait = NULL;
msq->msg_cbytes = msq->msg_qnum = 0;
msq->msg_lspid = msq->msg_lrpid = 0;
- msq->msg_stime = msq->msg_rtime = 0;
- msq->msg_qbytes = MSGMNB;
- msq->msg_ctime = CURRENT_TIME;
+ msq->u.msg_stime = msq->u.msg_rtime = 0;
+ msq->msg_qbytes = msgmnb;
+ msq->u.msg_ctime = CURRENT_TIME;
if (id > max_msqid)
max_msqid = id;
msgque[id] = msq;
used_queues++;
wake_up (&msg_lock);
- return (unsigned int) msq->msg_perm.seq * MSGMNI + id;
+ return (unsigned int) msq->u.msg_perm.seq * MSGMNI + id;
}

asmlinkage int sys_msgget (key_t key, int msgflg)
{
int id, ret = -EPERM;
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;

lock_kernel();
if (key == IPC_PRIVATE)
@@ -317,10 +341,10 @@
msq = msgque[id];
if (msq == IPC_UNUSED || msq == IPC_NOID)
ret = -EIDRM;
- else if (ipcperms(&msq->msg_perm, msgflg))
+ else if (ipcperms(&msq->u.msg_perm, msgflg))
ret = -EACCES;
else
- ret = (unsigned int) msq->msg_perm.seq * MSGMNI + id;
+ ret = (unsigned int) msq->u.msg_perm.seq * MSGMNI + id;
}
unlock_kernel();
return ret;
@@ -328,24 +352,26 @@

static void freeque (int id)
{
- struct msqid_ds *msq = msgque[id];
+ struct msqid_ds_kernel *msq = msgque[id];
struct msg *msgp, *msgh;

- msq->msg_perm.seq++;
+ msq->u.msg_perm.seq++;
msg_seq = (msg_seq+1) % ((unsigned)(1<<31)/MSGMNI); /* increment, but avoid overflow */
msgbytes -= msq->msg_cbytes;
if (id == max_msqid)
while (max_msqid && (msgque[--max_msqid] == IPC_UNUSED));
- msgque[id] = (struct msqid_ds *) IPC_UNUSED;
+ msgque[id] = (struct msqid_ds_kernel *) IPC_UNUSED;
used_queues--;
while (waitqueue_active(&msq->rwait) || waitqueue_active(&msq->wwait)) {
wake_up (&msq->rwait);
wake_up (&msq->wwait);
schedule();
}
- for (msgp = msq->msg_first; msgp; msgp = msgh ) {
+ for (msgp = msq->u.msg_first; msgp; msgp = msgh ) {
msgh = msgp->msg_next;
msghdrs--;
+ if (msgp->msg_ts >= MSGMAX)
+ vfree(msgp->msg_spot);
kfree(msgp);
}
kfree(msq);
@@ -354,9 +380,10 @@
asmlinkage int sys_msgctl (int msqid, int cmd, struct msqid_ds *buf)
{
int id, err = -EINVAL;
- struct msqid_ds *msq;
+ struct msqid_ds_kernel *msq;
struct msqid_ds tbuf;
struct ipc_perm *ipcp;
+ unsigned int msg_qbytes;

lock_kernel();
if (msqid < 0 || cmd < 0)
@@ -370,17 +397,20 @@
{
struct msginfo msginfo;
msginfo.msgmni = MSGMNI;
- msginfo.msgmax = MSGMAX;
- msginfo.msgmnb = MSGMNB;
- msginfo.msgmap = MSGMAP;
- msginfo.msgpool = MSGPOOL;
- msginfo.msgtql = MSGTQL;
+ msginfo.msgmax = msgmax;
+ msginfo.msgmnb = msgmnb;
msginfo.msgssz = MSGSSZ;
msginfo.msgseg = MSGSEG;
if (cmd == MSG_INFO) {
- msginfo.msgpool = used_queues;
+ /* was used_queues ? */
+ msginfo.msgpool = msgbytes;
msginfo.msgmap = msghdrs;
- msginfo.msgtql = msgbytes;
+ /* was msgbytes ? */
+ msginfo.msgtql = used_queues;
+ } else {
+ msginfo.msgpool = msgpool/1024;
+ msginfo.msgmap = MSGMAP;
+ msginfo.msgtql = MSGTQL;
}

err = -EFAULT;
@@ -399,16 +429,18 @@
if (msq == IPC_UNUSED || msq == IPC_NOID)
goto out;
err = -EACCES;
- if (ipcperms (&msq->msg_perm, S_IRUGO))
+ if (ipcperms (&msq->u.msg_perm, S_IRUGO))
goto out;
- id = (unsigned int) msq->msg_perm.seq * MSGMNI + msqid;
- tbuf.msg_perm = msq->msg_perm;
- tbuf.msg_stime = msq->msg_stime;
- tbuf.msg_rtime = msq->msg_rtime;
- tbuf.msg_ctime = msq->msg_ctime;
- tbuf.msg_cbytes = msq->msg_cbytes;
+ id = (unsigned int) msq->u.msg_perm.seq * MSGMNI + msqid;
+ tbuf.u.msg_perm = msq->u.msg_perm;
+ tbuf.u.msg_stime = msq->u.msg_stime;
+ tbuf.u.msg_rtime = msq->u.msg_rtime;
+ tbuf.u.msg_ctime = msq->u.msg_ctime;
+ tbuf.c.msg_cbytes = msq->msg_cbytes;
+ tbuf.q.msg_qbytes = msq->msg_qbytes;
+ tbuf.old_msg_cbytes = (unsigned short)msq->msg_cbytes;
tbuf.msg_qnum = msq->msg_qnum;
- tbuf.msg_qbytes = msq->msg_qbytes;
+ tbuf.old_msg_qbytes = (unsigned short)msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
err = -EFAULT;
@@ -435,22 +467,24 @@
if (msq == IPC_UNUSED || msq == IPC_NOID)
goto out;
err = -EIDRM;
- if (msq->msg_perm.seq != (unsigned int) msqid / MSGMNI)
+ if (msq->u.msg_perm.seq != (unsigned int) msqid / MSGMNI)
goto out;
- ipcp = &msq->msg_perm;
+ ipcp = &msq->u.msg_perm;

switch (cmd) {
case IPC_STAT:
err = -EACCES;
if (ipcperms (ipcp, S_IRUGO))
goto out;
- tbuf.msg_perm = msq->msg_perm;
- tbuf.msg_stime = msq->msg_stime;
- tbuf.msg_rtime = msq->msg_rtime;
- tbuf.msg_ctime = msq->msg_ctime;
- tbuf.msg_cbytes = msq->msg_cbytes;
+ tbuf.u.msg_perm = msq->u.msg_perm;
+ tbuf.u.msg_stime = msq->u.msg_stime;
+ tbuf.u.msg_rtime = msq->u.msg_rtime;
+ tbuf.u.msg_ctime = msq->u.msg_ctime;
+ tbuf.c.msg_cbytes = msq->msg_cbytes;
+ tbuf.q.msg_qbytes = msq->msg_qbytes;
+ tbuf.old_msg_cbytes = (unsigned short)msq->msg_cbytes;
tbuf.msg_qnum = msq->msg_qnum;
- tbuf.msg_qbytes = msq->msg_qbytes;
+ tbuf.old_msg_qbytes = (unsigned short)msq->msg_qbytes;
tbuf.msg_lspid = msq->msg_lspid;
tbuf.msg_lrpid = msq->msg_lrpid;
err = -EFAULT;
@@ -463,14 +497,18 @@
current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
/* We _could_ check for CAP_CHOWN above, but we don't */
goto out;
- if (tbuf.msg_qbytes > MSGMNB && !capable(CAP_SYS_RESOURCE))
+ if (tbuf.old_msg_qbytes == 0)
+ msg_qbytes = tbuf.q.msg_qbytes;
+ else
+ msg_qbytes = tbuf.old_msg_qbytes;
+ if (msg_qbytes > msgmnb && !capable(CAP_SYS_RESOURCE))
goto out;
- msq->msg_qbytes = tbuf.msg_qbytes;
- ipcp->uid = tbuf.msg_perm.uid;
- ipcp->gid = tbuf.msg_perm.gid;
+ msq->msg_qbytes = msg_qbytes;
+ ipcp->uid = tbuf.u.msg_perm.uid;
+ ipcp->gid = tbuf.u.msg_perm.gid;
ipcp->mode = (ipcp->mode & ~S_IRWXUGO) |
- (S_IRWXUGO & tbuf.msg_perm.mode);
- msq->msg_ctime = CURRENT_TIME;
+ (S_IRWXUGO & tbuf.u.msg_perm.mode);
+ msq->u.msg_ctime = CURRENT_TIME;
err = 0;
goto out;
case IPC_RMID:

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:52    [W:0.057 / U:0.592 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site