summaryrefslogtreecommitdiffstats
path: root/sys/kern/sysv_msg.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/sysv_msg.c')
-rw-r--r--sys/kern/sysv_msg.c53
1 files changed, 45 insertions, 8 deletions
diff --git a/sys/kern/sysv_msg.c b/sys/kern/sysv_msg.c
index 3e67bd0..eb451f9 100644
--- a/sys/kern/sysv_msg.c
+++ b/sys/kern/sysv_msg.c
@@ -63,6 +63,7 @@ __FBSDID("$FreeBSD$");
#include <sys/mutex.h>
#include <sys/module.h>
#include <sys/msg.h>
+#include <sys/racct.h>
#include <sys/syscall.h>
#include <sys/syscallsubr.h>
#include <sys/sysent.h>
@@ -466,6 +467,9 @@ kern_msgctl(td, msqid, cmd, msqbuf)
}
#endif
+ racct_sub_cred(msqkptr->cred, RACCT_NMSGQ, 1);
+ racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, msqkptr->u.msg_qnum);
+ racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msqkptr->u.msg_cbytes);
crfree(msqkptr->cred);
msqkptr->cred = NULL;
@@ -616,6 +620,13 @@ msgget(td, uap)
error = ENOSPC;
goto done2;
}
+ PROC_LOCK(td->td_proc);
+ error = racct_add(td->td_proc, RACCT_NMSGQ, 1);
+ PROC_UNLOCK(td->td_proc);
+ if (error != 0) {
+ error = ENOSPC;
+ goto done2;
+ }
DPRINTF(("msqid %d is available\n", msqid));
msqkptr->u.msg_perm.key = key;
msqkptr->u.msg_perm.cuid = cred->cr_uid;
@@ -675,6 +686,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
register struct msqid_kernel *msqkptr;
register struct msg *msghdr;
short next;
+ size_t saved_msgsz;
if (!prison_allow(td->td_ucred, PR_ALLOW_SYSVIPC))
return (ENOSYS);
@@ -712,6 +724,21 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
goto done2;
#endif
+ PROC_LOCK(td->td_proc);
+ if (racct_add(td->td_proc, RACCT_MSGQQUEUED, 1)) {
+ PROC_UNLOCK(td->td_proc);
+ error = EAGAIN;
+ goto done2;
+ }
+ saved_msgsz = msgsz;
+ if (racct_add(td->td_proc, RACCT_MSGQSIZE, msgsz)) {
+ racct_sub(td->td_proc, RACCT_MSGQQUEUED, 1);
+ PROC_UNLOCK(td->td_proc);
+ error = EAGAIN;
+ goto done2;
+ }
+ PROC_UNLOCK(td->td_proc);
+
segs_needed = (msgsz + msginfo.msgssz - 1) / msginfo.msgssz;
DPRINTF(("msgsz=%zu, msgssz=%d, segs_needed=%d\n", msgsz,
msginfo.msgssz, segs_needed));
@@ -726,7 +753,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
if (msgsz > msqkptr->u.msg_qbytes) {
DPRINTF(("msgsz > msqkptr->u.msg_qbytes\n"));
error = EINVAL;
- goto done2;
+ goto done3;
}
if (msqkptr->u.msg_perm.mode & MSG_LOCKED) {
@@ -753,7 +780,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
DPRINTF(("need more resources but caller "
"doesn't want to wait\n"));
error = EAGAIN;
- goto done2;
+ goto done3;
}
if ((msqkptr->u.msg_perm.mode & MSG_LOCKED) != 0) {
@@ -779,7 +806,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
if (error != 0) {
DPRINTF(("msgsnd: interrupted system call\n"));
error = EINTR;
- goto done2;
+ goto done3;
}
/*
@@ -789,7 +816,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
if (msqkptr->u.msg_qbytes == 0) {
DPRINTF(("msqid deleted\n"));
error = EIDRM;
- goto done2;
+ goto done3;
}
} else {
@@ -871,7 +898,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
wakeup(msqkptr);
DPRINTF(("mtype (%ld) < 1\n", msghdr->msg_type));
error = EINVAL;
- goto done2;
+ goto done3;
}
/*
@@ -898,7 +925,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
msg_freehdr(msghdr);
msqkptr->u.msg_perm.mode &= ~MSG_LOCKED;
wakeup(msqkptr);
- goto done2;
+ goto done3;
}
mtx_lock(&msq_mtx);
msgsz -= tlen;
@@ -922,7 +949,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
msg_freehdr(msghdr);
wakeup(msqkptr);
error = EIDRM;
- goto done2;
+ goto done3;
}
#ifdef MAC
@@ -941,7 +968,7 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
if (error != 0) {
msg_freehdr(msghdr);
wakeup(msqkptr);
- goto done2;
+ goto done3;
}
#endif
@@ -964,6 +991,13 @@ kern_msgsnd(td, msqid, msgp, msgsz, msgflg, mtype)
wakeup(msqkptr);
td->td_retval[0] = 0;
+done3:
+ if (error != 0) {
+ PROC_LOCK(td->td_proc);
+ racct_sub(td->td_proc, RACCT_MSGQQUEUED, 1);
+ racct_sub(td->td_proc, RACCT_MSGQSIZE, saved_msgsz);
+ PROC_UNLOCK(td->td_proc);
+ }
done2:
mtx_unlock(&msq_mtx);
return (error);
@@ -1197,6 +1231,9 @@ kern_msgrcv(td, msqid, msgp, msgsz, msgtyp, msgflg, mtype)
msqkptr->u.msg_lrpid = td->td_proc->p_pid;
msqkptr->u.msg_rtime = time_second;
+ racct_sub_cred(msqkptr->cred, RACCT_MSGQQUEUED, 1);
+ racct_sub_cred(msqkptr->cred, RACCT_MSGQSIZE, msghdr->msg_ts);
+
/*
* Make msgsz the actual amount that we'll be returning.
* Note that this effectively truncates the message if it is too long
OpenPOWER on IntegriCloud