* Occurs in several places in the IPC code.
* Chris Evans, <chris@ferret.lmh.ox.ac.uk>
* Nov 1999 - ipc helper functions, unified SMP locking
- * Manfred Spraul <manfreds@colorfullife.com>
+ * Manfred Spraul <manfred@colorfullife.com>
* Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().
* Mingming Cao <cmm@us.ibm.com>
+ * Mar 2006 - support for audit of ipc object properties
+ * Dustin Kirkland <dustin.kirkland@us.ibm.com>
*/
#include <linux/config.h>
#include <linux/smp_lock.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
+#include <linux/capability.h>
#include <linux/highuid.h>
#include <linux/security.h>
#include <linux/rcupdate.h>
#include <linux/workqueue.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
+#include <linux/audit.h>
#include <asm/unistd.h>
void __init ipc_init_ids(struct ipc_ids* ids, int size)
{
int i;
- sema_init(&ids->sem,1);
+
+ mutex_init(&ids->mutex);
if(size > IPCMNI)
size = IPCMNI;
* @ids: Identifier set
* @key: The key to find
*
- * Requires ipc_ids.sem locked.
+ * Requires ipc_ids.mutex locked.
* Returns the identifier if found or -1 if not.
*/
/*
* rcu_dereference() is not needed here
- * since ipc_ids.sem is held
+ * since ipc_ids.mutex is held
*/
for (id = 0; id <= max_id; id++) {
p = ids->entries->p[id];
}
/*
- * Requires ipc_ids.sem locked
+ * Requires ipc_ids.mutex locked
*/
static int grow_ary(struct ipc_ids* ids, int newsize)
{
if(new == NULL)
return size;
new->size = newsize;
- memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size +
- sizeof(struct ipc_id_ary));
+ memcpy(new->p, ids->entries->p, sizeof(struct kern_ipc_perm *)*size);
for(i=size;i<newsize;i++) {
new->p[i] = NULL;
}
* is returned. The list is returned in a locked state on success.
* On failure the list is not locked and -1 is returned.
*
- * Called with ipc_ids.sem held.
+ * Called with ipc_ids.mutex held.
*/
int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)
/*
* rcu_dereference()() is not needed here since
- * ipc_ids.sem is held
+ * ipc_ids.mutex is held
*/
for (id = 0; id < size; id++) {
if(ids->entries->p[id] == NULL)
* fed an invalid identifier. The entry is removed and internal
* variables recomputed. The object associated with the identifier
* is returned.
- * ipc_ids.sem and the spinlock for this ID is hold before this function
+ * ipc_ids.mutex and the spinlock for this ID is hold before this function
* is called, and remain locked on the exit.
*/
{
struct kern_ipc_perm* p;
int lid = id % SEQ_MULTIPLIER;
- if(lid >= ids->entries->size)
- BUG();
+ BUG_ON(lid >= ids->entries->size);
/*
* do not need a rcu_dereference()() here to force ordering
- * on Alpha, since the ipc_ids.sem is held.
+ * on Alpha, since the ipc_ids.mutex is held.
*/
p = ids->entries->p[lid];
ids->entries->p[lid] = NULL;
- if(p==NULL)
- BUG();
+ BUG_ON(p==NULL);
ids->in_use--;
if (lid == ids->max_id) {
int ipcperms (struct kern_ipc_perm *ipcp, short flag)
{ /* flag will most probably be 0 or S_...UGO from <linux/stat.h> */
- int requested_mode, granted_mode;
+ int requested_mode, granted_mode, err;
+ if (unlikely((err = audit_ipc_obj(ipcp))))
+ return err;
requested_mode = (flag >> 6) | (flag >> 3) | flag;
granted_mode = ipcp->mode;
if (current->euid == ipcp->cuid || current->euid == ipcp->uid)
/*
* So far only shm_get_stat() calls ipc_get() via shm_get(), so ipc_get()
- * is called with shm_ids.sem locked. Since grow_ary() is also called with
- * shm_ids.sem down(for Shared Memory), there is no need to add read
+ * is called with shm_ids.mutex locked. Since grow_ary() is also called with
+ * shm_ids.mutex down(for Shared Memory), there is no need to add read
* barriers here to gurantee the writes in grow_ary() are seen in order
* here (for Alpha).
*
- * However ipc_get() itself does not necessary require ipc_ids.sem down. So
- * if in the future ipc_get() is used by other places without ipc_ids.sem
+ * However ipc_get() itself does not necessary require ipc_ids.mutex down. So
+ * if in the future ipc_get() is used by other places without ipc_ids.mutex
* down, then ipc_get() needs read memery barriers as ipc_lock() does.
*/
struct kern_ipc_perm* ipc_get(struct ipc_ids* ids, int id)
* Take the lock - this will be released by the corresponding
* call to stop().
*/
- down(&iface->ids->sem);
+ mutex_lock(&iface->ids->mutex);
/* pos < 0 is invalid */
if (*pos < 0)
ipc_unlock(ipc);
/* Release the lock we took in start() */
- up(&iface->ids->sem);
+ mutex_unlock(&iface->ids->mutex);
}
static int sysvipc_proc_show(struct seq_file *s, void *it)