util.h 4.75 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1 2 3 4
/*
 * linux/ipc/util.h
 * Copyright (C) 1999 Christoph Rohland
 *
5
 * ipc helper functions (c) 1999 Manfred Spraul <manfred@colorfullife.com>
6 7
 * namespaces support.      2006 OpenVZ, SWsoft Inc.
 *                               Pavel Emelianov <xemul@openvz.org>
Linus Torvalds's avatar
Linus Torvalds committed
8 9 10 11 12
 */

#ifndef _IPC_UTIL_H
#define _IPC_UTIL_H

Nadia Derbey's avatar
Nadia Derbey committed
13
#include <linux/idr.h>
14
#include <linux/err.h>
Nadia Derbey's avatar
Nadia Derbey committed
15

Linus Torvalds's avatar
Linus Torvalds committed
16 17 18 19 20 21 22
#define USHRT_MAX 0xffff
#define SEQ_MULTIPLIER	(IPCMNI)

void sem_init (void);
void msg_init (void);
void shm_init (void);

23 24 25 26 27 28 29 30
int sem_init_ns(struct ipc_namespace *ns);
int msg_init_ns(struct ipc_namespace *ns);
int shm_init_ns(struct ipc_namespace *ns);

void sem_exit_ns(struct ipc_namespace *ns);
void msg_exit_ns(struct ipc_namespace *ns);
void shm_exit_ns(struct ipc_namespace *ns);

Linus Torvalds's avatar
Linus Torvalds committed
31 32 33 34
struct ipc_ids {
	int in_use;
	unsigned short seq;
	unsigned short seq_max;
Ingo Molnar's avatar
Ingo Molnar committed
35
	struct mutex mutex;
Nadia Derbey's avatar
Nadia Derbey committed
36
	struct idr ipcs_idr;
Linus Torvalds's avatar
Linus Torvalds committed
37 38
};

Nadia Derbey's avatar
Nadia Derbey committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
/*
 * Structure that holds the parameters needed by the ipc operations
 * (see after)
 */
struct ipc_params {
	key_t key;
	int flg;
	union {
		size_t size;	/* for shared memories */
		int nsems;	/* for semaphores */
	} u;			/* holds the getnew() specific param */
};

/*
 * Structure that holds some ipc operations. This structure is used to unify
 * the calls to sys_msgget(), sys_semget(), sys_shmget()
 *      . routine to call to create a new ipc object. Can be one of newque,
 *        newary, newseg
 *      . routine to call to call to check permissions for a new ipc object.
 *        Can be one of security_msg_associate, security_sem_associate,
 *        security_shm_associate
 *      . routine to call for an extra check if needed
 */
struct ipc_ops {
	int (*getnew) (struct ipc_namespace *, struct ipc_params *);
Nadia Derbey's avatar
Nadia Derbey committed
64 65
	int (*associate) (struct kern_ipc_perm *, int);
	int (*more_checks) (struct kern_ipc_perm *, struct ipc_params *);
Nadia Derbey's avatar
Nadia Derbey committed
66 67
};

68
struct seq_file;
69

Nadia Derbey's avatar
Nadia Derbey committed
70
void ipc_init_ids(struct ipc_ids *);
71 72
#ifdef CONFIG_PROC_FS
void __init ipc_init_proc_interface(const char *path, const char *header,
73
		int ids, int (*show)(struct seq_file *, void *));
74 75 76
#else
#define ipc_init_proc_interface(path, header, ids, show) do {} while (0)
#endif
Linus Torvalds's avatar
Linus Torvalds committed
77

78 79 80 81
#define IPC_SEM_IDS	0
#define IPC_MSG_IDS	1
#define IPC_SHM_IDS	2

82 83
#define ipcid_to_idx(id) ((id) % SEQ_MULTIPLIER)

Ingo Molnar's avatar
Ingo Molnar committed
84
/* must be called with ids->mutex acquired.*/
Nadia Derbey's avatar
Nadia Derbey committed
85 86
int ipc_addid(struct ipc_ids *, struct kern_ipc_perm *, int);
int ipc_get_maxid(struct ipc_ids *);
Linus Torvalds's avatar
Linus Torvalds committed
87 88

/* must be called with both locks acquired. */
Nadia Derbey's avatar
Nadia Derbey committed
89
void ipc_rmid(struct ipc_ids *, struct kern_ipc_perm *);
Linus Torvalds's avatar
Linus Torvalds committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108

int ipcperms (struct kern_ipc_perm *ipcp, short flg);

/* for rare, potentially huge allocations.
 * both function can sleep
 */
void* ipc_alloc(int size);
void ipc_free(void* ptr, int size);

/*
 * For allocation that need to be freed by RCU.
 * Objects are reference counted, they start with reference count 1.
 * getref increases the refcount, the putref call that reduces the recount
 * to 0 schedules the rcu destruction. Caller must guarantee locking.
 */
void* ipc_rcu_alloc(int size);
void ipc_rcu_getref(void *ptr);
void ipc_rcu_putref(void *ptr);

109
struct kern_ipc_perm *ipc_lock(struct ipc_ids *, int);
Linus Torvalds's avatar
Linus Torvalds committed
110 111 112 113 114
int ipc_buildid(struct ipc_ids* ids, int id, int seq);

void kernel_to_ipc64_perm(struct kern_ipc_perm *in, struct ipc64_perm *out);
void ipc64_perm_to_ipc_perm(struct ipc64_perm *in, struct ipc_perm *out);

115
#if defined(__ia64__) || defined(__x86_64__) || defined(__hppa__) || defined(__XTENSA__)
Linus Torvalds's avatar
Linus Torvalds committed
116 117 118 119 120 121 122 123 124
  /* On IA-64, we always use the "64-bit version" of the IPC structures.  */ 
# define ipc_parse_version(cmd)	IPC_64
#else
int ipc_parse_version (int *cmd);
#endif

extern void free_msg(struct msg_msg *msg);
extern struct msg_msg *load_msg(const void __user *src, int len);
extern int store_msg(void __user *dest, struct msg_msg *msg, int len);
Nadia Derbey's avatar
Nadia Derbey committed
125 126 127 128 129
extern int ipcget_new(struct ipc_namespace *, struct ipc_ids *,
			struct ipc_ops *, struct ipc_params *);
extern int ipcget_public(struct ipc_namespace *, struct ipc_ids *,
			struct ipc_ops *, struct ipc_params *);

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
static inline int ipc_checkid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp,
				int uid)
{
	if (uid / SEQ_MULTIPLIER != ipcp->seq)
		return 1;
	return 0;
}

static inline void ipc_lock_by_ptr(struct kern_ipc_perm *perm)
{
	rcu_read_lock();
	spin_lock(&perm->lock);
}

static inline void ipc_unlock(struct kern_ipc_perm *perm)
{
	spin_unlock(&perm->lock);
	rcu_read_unlock();
}

static inline struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids,
						int id)
{
	struct kern_ipc_perm *out;

	out = ipc_lock(ids, id);
	if (IS_ERR(out))
		return out;

	if (ipc_checkid(ids, out, id)) {
		ipc_unlock(out);
		return ERR_PTR(-EIDRM);
	}

	return out;
}

Nadia Derbey's avatar
Nadia Derbey committed
167 168 169 170 171 172 173 174
static inline int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,
			struct ipc_ops *ops, struct ipc_params *params)
{
	if (params->key == IPC_PRIVATE)
		return ipcget_new(ns, ids, ops, params);
	else
		return ipcget_public(ns, ids, ops, params);
}
Linus Torvalds's avatar
Linus Torvalds committed
175 176

#endif