/*1* linux/ipc/util.c2* Copyright (C) 1992 Krishna Balasubramanian3*4* Sep 1997 - Call suser() last after "normal" permission checks so we5* get BSD style process accounting right.6* Occurs in several places in the IPC code.7* Chris Evans, <[email protected]>8* Nov 1999 - ipc helper functions, unified SMP locking9* Manfred Spraul <[email protected]>10* Oct 2002 - One lock per IPC id. RCU ipc_free for lock-free grow_ary().11* Mingming Cao <[email protected]>12* Mar 2006 - support for audit of ipc object properties13* Dustin Kirkland <[email protected]>14* Jun 2006 - namespaces ssupport15* OpenVZ, SWsoft Inc.16* Pavel Emelianov <[email protected]>17*/1819#include <linux/mm.h>20#include <linux/shm.h>21#include <linux/init.h>22#include <linux/msg.h>23#include <linux/vmalloc.h>24#include <linux/slab.h>25#include <linux/capability.h>26#include <linux/highuid.h>27#include <linux/security.h>28#include <linux/rcupdate.h>29#include <linux/workqueue.h>30#include <linux/seq_file.h>31#include <linux/proc_fs.h>32#include <linux/audit.h>33#include <linux/nsproxy.h>34#include <linux/rwsem.h>35#include <linux/memory.h>36#include <linux/ipc_namespace.h>3738#include <asm/unistd.h>3940#include "util.h"4142struct ipc_proc_iface {43const char *path;44const char *header;45int ids;46int (*show)(struct seq_file *, void *);47};4849#ifdef CONFIG_MEMORY_HOTPLUG5051static void ipc_memory_notifier(struct work_struct *work)52{53ipcns_notify(IPCNS_MEMCHANGED);54}5556static DECLARE_WORK(ipc_memory_wq, ipc_memory_notifier);575859static int ipc_memory_callback(struct notifier_block *self,60unsigned long action, void *arg)61{62switch (action) {63case MEM_ONLINE: /* memory successfully brought online */64case MEM_OFFLINE: /* or offline: it's time to recompute msgmni */65/*66* This is done by invoking the ipcns notifier chain with the67* IPC_MEMCHANGED event.68* In order not to keep the lock on the hotplug memory chain69* for too long, queue a work item that will, when waken up,70* activate the ipcns notification chain.71* No need to keep several ipc work items on the queue.72*/73if (!work_pending(&ipc_memory_wq))74schedule_work(&ipc_memory_wq);75break;76case MEM_GOING_ONLINE:77case MEM_GOING_OFFLINE:78case MEM_CANCEL_ONLINE:79case MEM_CANCEL_OFFLINE:80default:81break;82}8384return NOTIFY_OK;85}8687#endif /* CONFIG_MEMORY_HOTPLUG */8889/**90* ipc_init - initialise IPC subsystem91*92* The various system5 IPC resources (semaphores, messages and shared93* memory) are initialised94* A callback routine is registered into the memory hotplug notifier95* chain: since msgmni scales to lowmem this callback routine will be96* called upon successful memory add / remove to recompute msmgni.97*/9899static int __init ipc_init(void)100{101sem_init();102msg_init();103shm_init();104hotplug_memory_notifier(ipc_memory_callback, IPC_CALLBACK_PRI);105register_ipcns_notifier(&init_ipc_ns);106return 0;107}108__initcall(ipc_init);109110/**111* ipc_init_ids - initialise IPC identifiers112* @ids: Identifier set113*114* Set up the sequence range to use for the ipc identifier range (limited115* below IPCMNI) then initialise the ids idr.116*/117118void ipc_init_ids(struct ipc_ids *ids)119{120init_rwsem(&ids->rw_mutex);121122ids->in_use = 0;123ids->seq = 0;124{125int seq_limit = INT_MAX/SEQ_MULTIPLIER;126if (seq_limit > USHRT_MAX)127ids->seq_max = USHRT_MAX;128else129ids->seq_max = seq_limit;130}131132idr_init(&ids->ipcs_idr);133}134135#ifdef CONFIG_PROC_FS136static const struct file_operations sysvipc_proc_fops;137/**138* ipc_init_proc_interface - Create a proc interface for sysipc types using a seq_file interface.139* @path: Path in procfs140* @header: Banner to be printed at the beginning of the file.141* @ids: ipc id table to iterate.142* @show: show routine.143*/144void __init ipc_init_proc_interface(const char *path, const char *header,145int ids, int (*show)(struct seq_file *, void *))146{147struct proc_dir_entry *pde;148struct ipc_proc_iface *iface;149150iface = kmalloc(sizeof(*iface), GFP_KERNEL);151if (!iface)152return;153iface->path = path;154iface->header = header;155iface->ids = ids;156iface->show = show;157158pde = proc_create_data(path,159S_IRUGO, /* world readable */160NULL, /* parent dir */161&sysvipc_proc_fops,162iface);163if (!pde) {164kfree(iface);165}166}167#endif168169/**170* ipc_findkey - find a key in an ipc identifier set171* @ids: Identifier set172* @key: The key to find173*174* Requires ipc_ids.rw_mutex locked.175* Returns the LOCKED pointer to the ipc structure if found or NULL176* if not.177* If key is found ipc points to the owning ipc structure178*/179180static struct kern_ipc_perm *ipc_findkey(struct ipc_ids *ids, key_t key)181{182struct kern_ipc_perm *ipc;183int next_id;184int total;185186for (total = 0, next_id = 0; total < ids->in_use; next_id++) {187ipc = idr_find(&ids->ipcs_idr, next_id);188189if (ipc == NULL)190continue;191192if (ipc->key != key) {193total++;194continue;195}196197ipc_lock_by_ptr(ipc);198return ipc;199}200201return NULL;202}203204/**205* ipc_get_maxid - get the last assigned id206* @ids: IPC identifier set207*208* Called with ipc_ids.rw_mutex held.209*/210211int ipc_get_maxid(struct ipc_ids *ids)212{213struct kern_ipc_perm *ipc;214int max_id = -1;215int total, id;216217if (ids->in_use == 0)218return -1;219220if (ids->in_use == IPCMNI)221return IPCMNI - 1;222223/* Look for the last assigned id */224total = 0;225for (id = 0; id < IPCMNI && total < ids->in_use; id++) {226ipc = idr_find(&ids->ipcs_idr, id);227if (ipc != NULL) {228max_id = id;229total++;230}231}232return max_id;233}234235/**236* ipc_addid - add an IPC identifier237* @ids: IPC identifier set238* @new: new IPC permission set239* @size: limit for the number of used ids240*241* Add an entry 'new' to the IPC ids idr. The permissions object is242* initialised and the first free entry is set up and the id assigned243* is returned. The 'new' entry is returned in a locked state on success.244* On failure the entry is not locked and a negative err-code is returned.245*246* Called with ipc_ids.rw_mutex held as a writer.247*/248249int ipc_addid(struct ipc_ids* ids, struct kern_ipc_perm* new, int size)250{251uid_t euid;252gid_t egid;253int id, err;254255if (size > IPCMNI)256size = IPCMNI;257258if (ids->in_use >= size)259return -ENOSPC;260261spin_lock_init(&new->lock);262new->deleted = 0;263rcu_read_lock();264spin_lock(&new->lock);265266err = idr_get_new(&ids->ipcs_idr, new, &id);267if (err) {268spin_unlock(&new->lock);269rcu_read_unlock();270return err;271}272273ids->in_use++;274275current_euid_egid(&euid, &egid);276new->cuid = new->uid = euid;277new->gid = new->cgid = egid;278279new->seq = ids->seq++;280if(ids->seq > ids->seq_max)281ids->seq = 0;282283new->id = ipc_buildid(id, new->seq);284return id;285}286287/**288* ipcget_new - create a new ipc object289* @ns: namespace290* @ids: IPC identifer set291* @ops: the actual creation routine to call292* @params: its parameters293*294* This routine is called by sys_msgget, sys_semget() and sys_shmget()295* when the key is IPC_PRIVATE.296*/297static int ipcget_new(struct ipc_namespace *ns, struct ipc_ids *ids,298struct ipc_ops *ops, struct ipc_params *params)299{300int err;301retry:302err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);303304if (!err)305return -ENOMEM;306307down_write(&ids->rw_mutex);308err = ops->getnew(ns, params);309up_write(&ids->rw_mutex);310311if (err == -EAGAIN)312goto retry;313314return err;315}316317/**318* ipc_check_perms - check security and permissions for an IPC319* @ns: IPC namespace320* @ipcp: ipc permission set321* @ops: the actual security routine to call322* @params: its parameters323*324* This routine is called by sys_msgget(), sys_semget() and sys_shmget()325* when the key is not IPC_PRIVATE and that key already exists in the326* ids IDR.327*328* On success, the IPC id is returned.329*330* It is called with ipc_ids.rw_mutex and ipcp->lock held.331*/332static int ipc_check_perms(struct ipc_namespace *ns,333struct kern_ipc_perm *ipcp,334struct ipc_ops *ops,335struct ipc_params *params)336{337int err;338339if (ipcperms(ns, ipcp, params->flg))340err = -EACCES;341else {342err = ops->associate(ipcp, params->flg);343if (!err)344err = ipcp->id;345}346347return err;348}349350/**351* ipcget_public - get an ipc object or create a new one352* @ns: namespace353* @ids: IPC identifer set354* @ops: the actual creation routine to call355* @params: its parameters356*357* This routine is called by sys_msgget, sys_semget() and sys_shmget()358* when the key is not IPC_PRIVATE.359* It adds a new entry if the key is not found and does some permission360* / security checkings if the key is found.361*362* On success, the ipc id is returned.363*/364static int ipcget_public(struct ipc_namespace *ns, struct ipc_ids *ids,365struct ipc_ops *ops, struct ipc_params *params)366{367struct kern_ipc_perm *ipcp;368int flg = params->flg;369int err;370retry:371err = idr_pre_get(&ids->ipcs_idr, GFP_KERNEL);372373/*374* Take the lock as a writer since we are potentially going to add375* a new entry + read locks are not "upgradable"376*/377down_write(&ids->rw_mutex);378ipcp = ipc_findkey(ids, params->key);379if (ipcp == NULL) {380/* key not used */381if (!(flg & IPC_CREAT))382err = -ENOENT;383else if (!err)384err = -ENOMEM;385else386err = ops->getnew(ns, params);387} else {388/* ipc object has been locked by ipc_findkey() */389390if (flg & IPC_CREAT && flg & IPC_EXCL)391err = -EEXIST;392else {393err = 0;394if (ops->more_checks)395err = ops->more_checks(ipcp, params);396if (!err)397/*398* ipc_check_perms returns the IPC id on399* success400*/401err = ipc_check_perms(ns, ipcp, ops, params);402}403ipc_unlock(ipcp);404}405up_write(&ids->rw_mutex);406407if (err == -EAGAIN)408goto retry;409410return err;411}412413414/**415* ipc_rmid - remove an IPC identifier416* @ids: IPC identifier set417* @ipcp: ipc perm structure containing the identifier to remove418*419* ipc_ids.rw_mutex (as a writer) and the spinlock for this ID are held420* before this function is called, and remain locked on the exit.421*/422423void ipc_rmid(struct ipc_ids *ids, struct kern_ipc_perm *ipcp)424{425int lid = ipcid_to_idx(ipcp->id);426427idr_remove(&ids->ipcs_idr, lid);428429ids->in_use--;430431ipcp->deleted = 1;432433return;434}435436/**437* ipc_alloc - allocate ipc space438* @size: size desired439*440* Allocate memory from the appropriate pools and return a pointer to it.441* NULL is returned if the allocation fails442*/443444void* ipc_alloc(int size)445{446void* out;447if(size > PAGE_SIZE)448out = vmalloc(size);449else450out = kmalloc(size, GFP_KERNEL);451return out;452}453454/**455* ipc_free - free ipc space456* @ptr: pointer returned by ipc_alloc457* @size: size of block458*459* Free a block created with ipc_alloc(). The caller must know the size460* used in the allocation call.461*/462463void ipc_free(void* ptr, int size)464{465if(size > PAGE_SIZE)466vfree(ptr);467else468kfree(ptr);469}470471/*472* rcu allocations:473* There are three headers that are prepended to the actual allocation:474* - during use: ipc_rcu_hdr.475* - during the rcu grace period: ipc_rcu_grace.476* - [only if vmalloc]: ipc_rcu_sched.477* Their lifetime doesn't overlap, thus the headers share the same memory.478* Unlike a normal union, they are right-aligned, thus some container_of479* forward/backward casting is necessary:480*/481struct ipc_rcu_hdr482{483int refcount;484int is_vmalloc;485void *data[0];486};487488489struct ipc_rcu_grace490{491struct rcu_head rcu;492/* "void *" makes sure alignment of following data is sane. */493void *data[0];494};495496struct ipc_rcu_sched497{498struct work_struct work;499/* "void *" makes sure alignment of following data is sane. */500void *data[0];501};502503#define HDRLEN_KMALLOC (sizeof(struct ipc_rcu_grace) > sizeof(struct ipc_rcu_hdr) ? \504sizeof(struct ipc_rcu_grace) : sizeof(struct ipc_rcu_hdr))505#define HDRLEN_VMALLOC (sizeof(struct ipc_rcu_sched) > HDRLEN_KMALLOC ? \506sizeof(struct ipc_rcu_sched) : HDRLEN_KMALLOC)507508static inline int rcu_use_vmalloc(int size)509{510/* Too big for a single page? */511if (HDRLEN_KMALLOC + size > PAGE_SIZE)512return 1;513return 0;514}515516/**517* ipc_rcu_alloc - allocate ipc and rcu space518* @size: size desired519*520* Allocate memory for the rcu header structure + the object.521* Returns the pointer to the object.522* NULL is returned if the allocation fails.523*/524525void* ipc_rcu_alloc(int size)526{527void* out;528/*529* We prepend the allocation with the rcu struct, and530* workqueue if necessary (for vmalloc).531*/532if (rcu_use_vmalloc(size)) {533out = vmalloc(HDRLEN_VMALLOC + size);534if (out) {535out += HDRLEN_VMALLOC;536container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 1;537container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;538}539} else {540out = kmalloc(HDRLEN_KMALLOC + size, GFP_KERNEL);541if (out) {542out += HDRLEN_KMALLOC;543container_of(out, struct ipc_rcu_hdr, data)->is_vmalloc = 0;544container_of(out, struct ipc_rcu_hdr, data)->refcount = 1;545}546}547548return out;549}550551void ipc_rcu_getref(void *ptr)552{553container_of(ptr, struct ipc_rcu_hdr, data)->refcount++;554}555556static void ipc_do_vfree(struct work_struct *work)557{558vfree(container_of(work, struct ipc_rcu_sched, work));559}560561/**562* ipc_schedule_free - free ipc + rcu space563* @head: RCU callback structure for queued work564*565* Since RCU callback function is called in bh,566* we need to defer the vfree to schedule_work().567*/568static void ipc_schedule_free(struct rcu_head *head)569{570struct ipc_rcu_grace *grace;571struct ipc_rcu_sched *sched;572573grace = container_of(head, struct ipc_rcu_grace, rcu);574sched = container_of(&(grace->data[0]), struct ipc_rcu_sched,575data[0]);576577INIT_WORK(&sched->work, ipc_do_vfree);578schedule_work(&sched->work);579}580581/**582* ipc_immediate_free - free ipc + rcu space583* @head: RCU callback structure that contains pointer to be freed584*585* Free from the RCU callback context.586*/587static void ipc_immediate_free(struct rcu_head *head)588{589struct ipc_rcu_grace *free =590container_of(head, struct ipc_rcu_grace, rcu);591kfree(free);592}593594void ipc_rcu_putref(void *ptr)595{596if (--container_of(ptr, struct ipc_rcu_hdr, data)->refcount > 0)597return;598599if (container_of(ptr, struct ipc_rcu_hdr, data)->is_vmalloc) {600call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,601ipc_schedule_free);602} else {603call_rcu(&container_of(ptr, struct ipc_rcu_grace, data)->rcu,604ipc_immediate_free);605}606}607608/**609* ipcperms - check IPC permissions610* @ns: IPC namespace611* @ipcp: IPC permission set612* @flag: desired permission set.613*614* Check user, group, other permissions for access615* to ipc resources. return 0 if allowed616*617* @flag will most probably be 0 or S_...UGO from <linux/stat.h>618*/619620int ipcperms(struct ipc_namespace *ns, struct kern_ipc_perm *ipcp, short flag)621{622uid_t euid = current_euid();623int requested_mode, granted_mode;624625audit_ipc_obj(ipcp);626requested_mode = (flag >> 6) | (flag >> 3) | flag;627granted_mode = ipcp->mode;628if (euid == ipcp->cuid ||629euid == ipcp->uid)630granted_mode >>= 6;631else if (in_group_p(ipcp->cgid) || in_group_p(ipcp->gid))632granted_mode >>= 3;633/* is there some bit set in requested_mode but not in granted_mode? */634if ((requested_mode & ~granted_mode & 0007) &&635!ns_capable(ns->user_ns, CAP_IPC_OWNER))636return -1;637638return security_ipc_permission(ipcp, flag);639}640641/*642* Functions to convert between the kern_ipc_perm structure and the643* old/new ipc_perm structures644*/645646/**647* kernel_to_ipc64_perm - convert kernel ipc permissions to user648* @in: kernel permissions649* @out: new style IPC permissions650*651* Turn the kernel object @in into a set of permissions descriptions652* for returning to userspace (@out).653*/654655656void kernel_to_ipc64_perm (struct kern_ipc_perm *in, struct ipc64_perm *out)657{658out->key = in->key;659out->uid = in->uid;660out->gid = in->gid;661out->cuid = in->cuid;662out->cgid = in->cgid;663out->mode = in->mode;664out->seq = in->seq;665}666667/**668* ipc64_perm_to_ipc_perm - convert new ipc permissions to old669* @in: new style IPC permissions670* @out: old style IPC permissions671*672* Turn the new style permissions object @in into a compatibility673* object and store it into the @out pointer.674*/675676void ipc64_perm_to_ipc_perm (struct ipc64_perm *in, struct ipc_perm *out)677{678out->key = in->key;679SET_UID(out->uid, in->uid);680SET_GID(out->gid, in->gid);681SET_UID(out->cuid, in->cuid);682SET_GID(out->cgid, in->cgid);683out->mode = in->mode;684out->seq = in->seq;685}686687/**688* ipc_lock - Lock an ipc structure without rw_mutex held689* @ids: IPC identifier set690* @id: ipc id to look for691*692* Look for an id in the ipc ids idr and lock the associated ipc object.693*694* The ipc object is locked on exit.695*/696697struct kern_ipc_perm *ipc_lock(struct ipc_ids *ids, int id)698{699struct kern_ipc_perm *out;700int lid = ipcid_to_idx(id);701702rcu_read_lock();703out = idr_find(&ids->ipcs_idr, lid);704if (out == NULL) {705rcu_read_unlock();706return ERR_PTR(-EINVAL);707}708709spin_lock(&out->lock);710711/* ipc_rmid() may have already freed the ID while ipc_lock712* was spinning: here verify that the structure is still valid713*/714if (out->deleted) {715spin_unlock(&out->lock);716rcu_read_unlock();717return ERR_PTR(-EINVAL);718}719720return out;721}722723struct kern_ipc_perm *ipc_lock_check(struct ipc_ids *ids, int id)724{725struct kern_ipc_perm *out;726727out = ipc_lock(ids, id);728if (IS_ERR(out))729return out;730731if (ipc_checkid(out, id)) {732ipc_unlock(out);733return ERR_PTR(-EIDRM);734}735736return out;737}738739/**740* ipcget - Common sys_*get() code741* @ns : namsepace742* @ids : IPC identifier set743* @ops : operations to be called on ipc object creation, permission checks744* and further checks745* @params : the parameters needed by the previous operations.746*747* Common routine called by sys_msgget(), sys_semget() and sys_shmget().748*/749int ipcget(struct ipc_namespace *ns, struct ipc_ids *ids,750struct ipc_ops *ops, struct ipc_params *params)751{752if (params->key == IPC_PRIVATE)753return ipcget_new(ns, ids, ops, params);754else755return ipcget_public(ns, ids, ops, params);756}757758/**759* ipc_update_perm - update the permissions of an IPC.760* @in: the permission given as input.761* @out: the permission of the ipc to set.762*/763void ipc_update_perm(struct ipc64_perm *in, struct kern_ipc_perm *out)764{765out->uid = in->uid;766out->gid = in->gid;767out->mode = (out->mode & ~S_IRWXUGO)768| (in->mode & S_IRWXUGO);769}770771/**772* ipcctl_pre_down - retrieve an ipc and check permissions for some IPC_XXX cmd773* @ns: the ipc namespace774* @ids: the table of ids where to look for the ipc775* @id: the id of the ipc to retrieve776* @cmd: the cmd to check777* @perm: the permission to set778* @extra_perm: one extra permission parameter used by msq779*780* This function does some common audit and permissions check for some IPC_XXX781* cmd and is called from semctl_down, shmctl_down and msgctl_down.782* It must be called without any lock held and783* - retrieves the ipc with the given id in the given table.784* - performs some audit and permission check, depending on the given cmd785* - returns the ipc with both ipc and rw_mutex locks held in case of success786* or an err-code without any lock held otherwise.787*/788struct kern_ipc_perm *ipcctl_pre_down(struct ipc_namespace *ns,789struct ipc_ids *ids, int id, int cmd,790struct ipc64_perm *perm, int extra_perm)791{792struct kern_ipc_perm *ipcp;793uid_t euid;794int err;795796down_write(&ids->rw_mutex);797ipcp = ipc_lock_check(ids, id);798if (IS_ERR(ipcp)) {799err = PTR_ERR(ipcp);800goto out_up;801}802803audit_ipc_obj(ipcp);804if (cmd == IPC_SET)805audit_ipc_set_perm(extra_perm, perm->uid,806perm->gid, perm->mode);807808euid = current_euid();809if (euid == ipcp->cuid || euid == ipcp->uid ||810ns_capable(ns->user_ns, CAP_SYS_ADMIN))811return ipcp;812813err = -EPERM;814ipc_unlock(ipcp);815out_up:816up_write(&ids->rw_mutex);817return ERR_PTR(err);818}819820#ifdef __ARCH_WANT_IPC_PARSE_VERSION821822823/**824* ipc_parse_version - IPC call version825* @cmd: pointer to command826*827* Return IPC_64 for new style IPC and IPC_OLD for old style IPC.828* The @cmd value is turned from an encoding command and version into829* just the command code.830*/831832int ipc_parse_version (int *cmd)833{834if (*cmd & IPC_64) {835*cmd ^= IPC_64;836return IPC_64;837} else {838return IPC_OLD;839}840}841842#endif /* __ARCH_WANT_IPC_PARSE_VERSION */843844#ifdef CONFIG_PROC_FS845struct ipc_proc_iter {846struct ipc_namespace *ns;847struct ipc_proc_iface *iface;848};849850/*851* This routine locks the ipc structure found at least at position pos.852*/853static struct kern_ipc_perm *sysvipc_find_ipc(struct ipc_ids *ids, loff_t pos,854loff_t *new_pos)855{856struct kern_ipc_perm *ipc;857int total, id;858859total = 0;860for (id = 0; id < pos && total < ids->in_use; id++) {861ipc = idr_find(&ids->ipcs_idr, id);862if (ipc != NULL)863total++;864}865866if (total >= ids->in_use)867return NULL;868869for ( ; pos < IPCMNI; pos++) {870ipc = idr_find(&ids->ipcs_idr, pos);871if (ipc != NULL) {872*new_pos = pos + 1;873ipc_lock_by_ptr(ipc);874return ipc;875}876}877878/* Out of range - return NULL to terminate iteration */879return NULL;880}881882static void *sysvipc_proc_next(struct seq_file *s, void *it, loff_t *pos)883{884struct ipc_proc_iter *iter = s->private;885struct ipc_proc_iface *iface = iter->iface;886struct kern_ipc_perm *ipc = it;887888/* If we had an ipc id locked before, unlock it */889if (ipc && ipc != SEQ_START_TOKEN)890ipc_unlock(ipc);891892return sysvipc_find_ipc(&iter->ns->ids[iface->ids], *pos, pos);893}894895/*896* File positions: pos 0 -> header, pos n -> ipc id = n - 1.897* SeqFile iterator: iterator value locked ipc pointer or SEQ_TOKEN_START.898*/899static void *sysvipc_proc_start(struct seq_file *s, loff_t *pos)900{901struct ipc_proc_iter *iter = s->private;902struct ipc_proc_iface *iface = iter->iface;903struct ipc_ids *ids;904905ids = &iter->ns->ids[iface->ids];906907/*908* Take the lock - this will be released by the corresponding909* call to stop().910*/911down_read(&ids->rw_mutex);912913/* pos < 0 is invalid */914if (*pos < 0)915return NULL;916917/* pos == 0 means header */918if (*pos == 0)919return SEQ_START_TOKEN;920921/* Find the (pos-1)th ipc */922return sysvipc_find_ipc(ids, *pos - 1, pos);923}924925static void sysvipc_proc_stop(struct seq_file *s, void *it)926{927struct kern_ipc_perm *ipc = it;928struct ipc_proc_iter *iter = s->private;929struct ipc_proc_iface *iface = iter->iface;930struct ipc_ids *ids;931932/* If we had a locked structure, release it */933if (ipc && ipc != SEQ_START_TOKEN)934ipc_unlock(ipc);935936ids = &iter->ns->ids[iface->ids];937/* Release the lock we took in start() */938up_read(&ids->rw_mutex);939}940941static int sysvipc_proc_show(struct seq_file *s, void *it)942{943struct ipc_proc_iter *iter = s->private;944struct ipc_proc_iface *iface = iter->iface;945946if (it == SEQ_START_TOKEN)947return seq_puts(s, iface->header);948949return iface->show(s, it);950}951952static const struct seq_operations sysvipc_proc_seqops = {953.start = sysvipc_proc_start,954.stop = sysvipc_proc_stop,955.next = sysvipc_proc_next,956.show = sysvipc_proc_show,957};958959static int sysvipc_proc_open(struct inode *inode, struct file *file)960{961int ret;962struct seq_file *seq;963struct ipc_proc_iter *iter;964965ret = -ENOMEM;966iter = kmalloc(sizeof(*iter), GFP_KERNEL);967if (!iter)968goto out;969970ret = seq_open(file, &sysvipc_proc_seqops);971if (ret)972goto out_kfree;973974seq = file->private_data;975seq->private = iter;976977iter->iface = PDE(inode)->data;978iter->ns = get_ipc_ns(current->nsproxy->ipc_ns);979out:980return ret;981out_kfree:982kfree(iter);983goto out;984}985986static int sysvipc_proc_release(struct inode *inode, struct file *file)987{988struct seq_file *seq = file->private_data;989struct ipc_proc_iter *iter = seq->private;990put_ipc_ns(iter->ns);991return seq_release_private(inode, file);992}993994static const struct file_operations sysvipc_proc_fops = {995.open = sysvipc_proc_open,996.read = seq_read,997.llseek = seq_lseek,998.release = sysvipc_proc_release,999};1000#endif /* CONFIG_PROC_FS */100110021003